在FeignClientFactoryBean的<T> T getTarget()方法。
<T> T getTarget() {
//实例化Feign上下文对象FeignContext
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 (T) 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);
return (T) targeter.target(this, builder, context, new HardCodedTarget<>(
this.type, this.name, url));
}
上面FeignContext context = applicationContext.getBean(FeignContext.class);
直接的在容器里面拿FeignContext的对象,那这个对象是什么时候用注册到spring的呢,
FeignAutoConfiguration配置类,里面的
@Autowired(required = false)
private List<FeignClientSpecification> configurations = new ArrayList<>();
直接拿到了我们在(一)里面讲的注册的FeignClientSpecification包括默认的和各个feignCliet配置的 configuration
然而,当我们引入了 sleuth之后,获取的 feignContext确是 TraceFeignClientAutoConfiguration中配置的实例 sleuthFeignContext:这是因为primary的配置导致的。
如下
image.png
那这个feignContext是在哪里初始化的呢。
@Configuration
@ConditionalOnClass(Feign.class)
@EnableConfigurationProperties({FeignClientProperties.class, FeignHttpClientProperties.class})
public class FeignAutoConfiguration {
@Autowired(required = false)
private List<FeignClientSpecification> configurations = new ArrayList<>();
@Bean
public HasFeatures feignFeature() {
return HasFeatures.namedFeature("Feign", Feign.class);
}
@Bean
public FeignContext feignContext() {
FeignContext context = new FeignContext();
context.setConfigurations(this.configurations);
return context;
}
}
我们看到FeignAutoConfiguration在里面有个FeignContext的bean,但是没有用这个bean,在代码里面看到通过FeignContextBeanPostProcessor接口将FeignContext的bean强转成了TraceFeignContext
image.png
网友评论