文章目录
spring-cloud-openfeign-core-2.1.1.RELEASE.jar 中 HystrixFeign 的详细构建过程:
@EnableFeignClients -> FeignClientsRegistrar 扫描 @Feign注解的类 -> FeignClientFactoryBean通过Targeter生产FeignClient -> Targeter通过Feign.Builder构建Feign -> Feign.Builder
1. 准备工作(配置)
- FeignAutoConfiguration自动配置类
@Configuration
@ConditionalOnClass(name = "feign.hystrix.HystrixFeign")
protected static class HystrixFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new HystrixTargeter();
}
}
@Configuration
@ConditionalOnMissingClass("feign.hystrix.HystrixFeign")
protected static class DefaultFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new DefaultTargeter();
}
}
-
feign.hystrix.HystrixFeign类存在时,将
HystrixTargeter
注册为Targeter
类型的 bean -
feign.hystrix.HystrixFeign类不存在时,使用
DefaultTargeter
。 -
看起来似乎可以使用自定义的Targeter代替Hystrix或默认的,这样就可以自定义各种功能了。实际上不行,因为
Targeter
是 package 访问级别的。 -
FeignClientsConfiguration
@Configuration
public class FeignClientsConfiguration {
@Bean
@ConditionalOnMissingBean
public Retryer feignRetryer() {
return Retryer.NEVER_RETRY;
}
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
public Feign.Builder feignBuilder(Retryer retryer) {
return Feign.builder().retryer(retryer);
}
@Configuration
@ConditionalOnClass({
HystrixCommand.class, HystrixFeign.class })
protected static class HystrixFeignConfiguration {
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "feign.hystrix.enabled")
public Feign.Builder feignHystrixBuilder() {
return HystrixFeign.builder();
}
}
}
重要:Feign 以及内部类 Feign.Builder 都是 public 访问级别,可以注入自定义的bean。
2.EnableFeignClients与FeignClientsRegistrar类
将使用@FeignClient注解的类注册成spring bean,并使用注解中的配置
- 在@EnableFeignClients注解中导入FeignClientsRegistrar类
- FeignClientsRegistrar类实现了ImportBeanDefinitionRegistrar类,会由spring框架执行实现方法
registerBeanDefinitions(AnnotationMetaData, BeanDefinitionRegistry)
- FeignClientsRegistrar中的
registerBeanDefinitions
方法调用两个方法registerDefaultConfiguration
:注册默认的配置registerFeignClients
:注册Feign客户端(重点)
registerFeignClients
:获取@EnableFeignClients
注解中定义的配置扫描feign客户端registerFeignClients
:通过registerFeignClient(BeanDefinitionRegistry, AnnotationMetadata, Map)
方法注册每一个feignClient,过程:先获取@FeignClient
注解中定义的配置,将配置应用在spring bean 工厂FeignClientFactoryBean
, 通过工厂类FeignClientFactoryBean
为每一个使用@FeignClient
注解的类生产FeignClient
,详细过程见下一节
3.FeignClientFactoryBean
FeignClient工厂bean。
class FeignClientFactoryBean
implements FactoryBean<Object>, InitializingBean, ApplicationContextAware{
//...
}
通过实现方法 FactoryBean#getObject()
来由spring框架生产FeignClient。
@Override
public Object getObject() throws Exception {
return getTarget();
}
/**
* 获得目标
* 1. 获得FeignContext
* 2. 从FeignContext中获得Feign构建器Feign.Builder
* 3. 从FeignContext中获得Client,判断是否进行负载均衡
* 4. 从FeignContext中获得Target,并执行Target的默认方法target(FeignClientFactoryBean, Feign.Builder,
FeignContext, Target.HardCodedTarget<T>);
* 5.由于一开始注入的Feign.Builder是HystrixFeign.Builder,则此处是调用HystrixFeign.Builder里的对应方法
*/
<T> T getTarget() {
FeignContext context = this.applicationContext.getBean(FeignContext.class);
Feign.Builder builder = feign(context);
//省略部分代码
// ......
Client client = getOptional(context, Client.class);
if (client != null) {
if (client instanceof LoadBalancerFeignClient