Spring|Spring Boot Feign调用探究(二)
今天我们具体分析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 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
【Spring|Spring Boot Feign调用探究(二)】下面的代码块是具体调用的逻辑:
//加载启动类的中注册器
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
推荐阅读
- Spring Cloud Alibaba入门九:Nocas配置中心(入门)
- Spring功能介绍SpringMVC集成Java Bean Validation实现参数检验功
- springboot|springboot项目配置多数据库连接
- spring|eureka使用总结
- SpringBoot|SpringBoot+Vue从零开始做网站8-全局异常处理和使用mybatis-plus分页插件
- #|Spring Framework
- 笔记|xjar加密jar包springboot(实用,方便,包你学会)
- vue.js|Java毕业设计(基于SpringBoot+Vue前后分离的社区健康疫情防控系统)
- springboot 文件上传和下载
- springboot 全局异常捕获