关于springboot:Spring-Boot-Feign调用探究二

明天咱们具体分析FeignClientFactoryBean的作用,剖析之前先贴出来@EnableFeignClients的局部细节:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
}

为什么要贴出@EnableFeignClients呢?因为这个FeignClientsRegistrar类是咱们解析Feign类的入口,上面的代码块是FeignClientsRegistrar的局部细节:

private void registerFeignClient(BeanDefinitionRegistry registry,
            AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
        String className = annotationMetadata.getClassName();
        //赋值FeignClientFactoryBean类
        BeanDefinitionBuilder definition = BeanDefinitionBuilder
                .genericBeanDefinition(FeignClientFactoryBean.class);
}

由下面的代码片段,能够看到 FeignClientsRegistrar 会解析@EnableFeignClients注解,而后在构建BeanDefinition过程中,会注入FeignClientFactoryBean类,这样一来在后续实例化咱们申明的Feign类型的Bean过程中,会依据咱们配置的name/value,url等信息,实例化适合的FeignClient类。

当初咱们大抵理解了FeignClientFactoryBean的作用。而后再看一下FeignClientFactoryBean的getObject():

@Override
    public Object getObject() throws Exception {
        FeignContext context = applicationContext.getBean(FeignContext.class);
        Feign.Builder builder = feign(context);
        //如果咱们没有配置url
        if (!StringUtils.hasText(this.url)) {
            String url;
            if (!this.name.startsWith("http")) {
                url = "http://" + this.name;
            }
            else {
                url = this.name;
            }
            url += cleanPath();
            //调用负载平衡逻辑
            return loadBalance(builder, context, new HardCodedTarget<>(this.type,
                    this.name, url));
        }
        //如果配置了url
        if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
            this.url = "http://" + this.url;
        }
        String url = this.url + cleanPath();
        Client client = getOptional(context, Client.class);
        if (client != null) {
            if (client instanceof LoadBalancerFeignClient) {
                // not load balancing because we have a url,
                // but ribbon is on the classpath, so unwrap
                client = ((LoadBalancerFeignClient)client).getDelegate();
            }
            builder.client(client);
        }
        Targeter targeter = get(context, Targeter.class);
        //底层会构建HttpUrlConnection对象,其实也就是一般的http申请
        return targeter.target(this, builder, context, new HardCodedTarget<>(
                this.type, this.name, url));
    }

当初有没有恍然大迷瞪?!这个FeignClientFactoryBean决定了要创立哪一种的FeignClient对象!

那么问题来了,FeignClientsRegistrar类实现了ImportBeanDefinitionRegistrar接口,这个接口是干嘛用的呢?
图1
1:注册beanFactoy处理器。
2:解析所有的bean(ConfigurationClass)。
3:执行FeignClientsRegistrar类的 registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry)办法;

上面两个图是获取启动类中配置的注解信息,并且加载springbean容器中:因为咱们的启动类配置了@EnableFeignClients,@EnableFeignClients又引入了FeignClientsRegistrar.class,所以此时会加载FeignClientsRegistrar类;

图2
图3

上面的代码块是具体调用的逻辑:

//加载启动类的中注册器
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理