开启入口 @EnableFeignClients
1 加载bean 定义
@Import(FeignClientsRegistrar.class)
FeignClientsRegistrar 实现了ImportBeanDefinitionRegistrar, 重写了registerBeanDefinitions 将有注解@Feign 的类是实现扫描到了 BeanDefinition 容器中。并将FeignClientSpecification (构造函数)也加入其中
class FeignClientsRegistrar
implements ImportBeanDefinitionRegistrar
将FeignClientSpecification 将构造参数的bean 注册到 beanDefinition 容器中
FeignClientSpecification(String name, Class<?>[] configuration) {
this.name = name;
this.configuration = configuration;
}
最终fegin的为 FeignClientFactoryBean.class
2 实例化
FeignClientFactoryBean ioc 容器时,调用getObject()方法
public Object getObject() throws Exception {
return getTarget();
}
最终调用了 getTarget() 方法,返回Feignclient对象。
2.1 从ioc容器中获取到FeignContext 对象。
2.2 方法feign()中,最终会去调用getContext() 方法, 都会去每个FeignClietn 创建一个ioc容器, 并将当前的ioc 容器设置到其中。
由此可见,
NamedContextFactory类 成员变量中包含了 feiginClient 以beanName 对应的 容器对象。
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
每一次取对象,都是从contexts 对应的ioc 获取。
从ioc容器中获取到bean类型对象。 Feign.Builder.class, Encoder.class, Decoder.class, Contract.class;
feign.hystrix.enabled=true
HystrixFeign.Builder 继承了 Feign.Builder.class feign.hystrix 包下
feign.sentinel.enabled=true
SentinelFeign.Builder 继承了 Feign.Builder.class com.alibaba.cloud.sentinel.feign包下(如果没有引入该包, 则不再选择)
SeataSentinelFeignBuilder Feign.Builder 使用了 SeataFeignClient 。
3 自动化配置
@FeignRibbonClientAutoConfiguration
配置了三种请求负载均衡的客户端配置,最终根据注解条件将对应的bean 注入到 ioc容器中; 默认将 LoadBalancerFeignClient 注入到ioc容器中 ;
@FeignAutoConfiguration 默认会将 FeignContext, HystrixTargeter 等注入到ioc 容器
FeignContext 继承了NamedContextFactory, NamedContextFactory 实现了ApplicationContextAware. 所以便获取到了ioc 容器。
4 逻辑流转
HystrixFeign.Builder 继承了 Feign.Builder.class 重写 build(),并重写调回了super.build() 父类方法
feign.target(target) =》 回调用Feign.Builder 方法中的 target() 方法 =》 调取HystrixFeign.Builder (重写了build() 方法)=》 最终调用 Feign.Builder bulid() 方法。
=》ReflectiveFeign 方法的newInstance();
最终调用ReflectiveFeign 的 newInstance 方法返回代理对象。对注解@FeignClient 接口进行代理 并注入到ioc 容器中。
代理对象的所执行的逻辑 HystrixInvocationHandler 实现了InvocationHandler,类中invoke();
由 HystrixCommand.execute() 执行请求 (请求的发出居于RxJava 代码所编写)
。