明天咱们具体分析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());