spring初始化时会为每个声明的feignclient注册factorybean豆子,然后通过factorybean来生产feignclient豆子,所以现在关注点来到了FeignClientFactoryBean
可以看到它实现了3个接口,factorybean接口声明这是一个factorybean;InitializngBean接口用来在该豆子初始化结束时嵌入自定义逻辑,和@PostConstruct注解的功能一样;ApplicationContextAware接口顾名思义,实现该接口的类能够意识到ApplicationContext的存在。
feignclient的豆子是从FeignClientFactoryBean的getObject()方法生产的
/** * @param <T> the target type of the Feign client * @return a {@link Feign} client created with the specified data and the context * information */ <T> T getTarget() { FeignContext context = this.applicationContext.getBean(FeignContext.class); Feign.Builder builder = feign(context); if (!StringUtils.hasText(this.url)) { if (!this.name.startsWith("http")) { this.url = "http://" + this.name; } else { this.url = this.name; } this.url += cleanPath(); return (T) loadBalance(builder, context, new HardCodedTarget<>(this.type, this.name, this.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这个豆子,然而这个豆子是什么时候注册的呢?显然之前忽略了某个地方,这个地方就是FeignAutoConfiguration---spring boot的自动配置类。在spring.factories文件中指定了该类为自动配置类
可以看到在这里注册了FeignContext豆子。现在暂时关注点移到FeignContext中,待会再回来。
FeignContext是什么呢?
//TODO