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

38次阅读

共计 2417 个字符,预计需要花费 7 分钟才能阅读完成。

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

正文完
 0