所有文章

https://www.cnblogs.com/lay2017/p/11908715.html

正文

openfeign是一种声明式的webservice客户端调用框架。你只需要声明接口和一些简单的注解,就能像使用普通的Bean一样调用远程服务。本文将了解一下openfeign自动配置相关的东西,看看都做了哪些东西。

@EnableFeignClients开启openfeign

首先,我们从@EnableFeignClients这个开关注解开始了解。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients { // ...省略配置
}

这个注解导入了一个类FeignClientsRegistrar,这个类实现了ImportBeanDefinitionRegistrar接口,该接口用于向Bean容器种注册添加BeanDefinition。

为此,我们跟进FeignClientsRegistrar的registerBeanDefinitions方法,看看它注册了哪些东西。

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 注册默认配置
registerDefaultConfiguration(metadata, registry);
// 注册FeignClient接口的Bean
registerFeignClients(metadata, registry);
}

1、registerDefaultConfiguration方法将会读取@EnableFeignClients接口的属性,如果存在自定义配置类那么就会被注册到容器中。

2、registerFeignClients则会扫描所有注解了@FeignClient的接口,然后像spring本地Bean一样地注册到容器中。

扫描@FeignClient注解的接口

我们重点关注registerFeignClients方法,跟进代码

public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader); Set<String> basePackages; // 获取扫描路径 // 扫描所有路径,默认情况下扫描启动类下的路径
for (String basePackage : basePackages) {
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
// 遍历扫描到的FeignClient的Bean
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
// verify annotated class is an interface
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface"); Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName()); String name = getClientName(attributes);
// 注册FeignClient的配置
registerClientConfiguration(registry, name, attributes.get("configuration"));
// 注册FeignClient
registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}

方法中的核心逻辑就是扫描类路径,获取BeanDefinition,然后遍历进行注册。

跟进registerFeignClient注册方法

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
// 生成FeignClientFactoryBean这个BeanDefinition构造器
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class); // 将@FeignClient的注解属性添加到builder
definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("path", getPath(attributes));
String name = getName(attributes);
definition.addPropertyValue("name", name);
String contextId = getContextId(attributes);
definition.addPropertyValue("contextId", contextId);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); String alias = contextId + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition(); // ... BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[] { alias });
// 注册
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}

这里值得注意的是genericBeanDefinition方法最终生成的其实是FeignClientFactoryBean,registerBeanDefinition方法注册进容器的也是FeignClientFactoryBean。

而FeignClientFactoryBean向上直接实现了FactoryBean接口

FactoryBean接口是spring开放出来的,用于自定义Bean的生成过程。也就是说,spring将会通过调用FeignClientFactoryBean的getObject来获取@FeignClient注解的接口对应的Bean对象。

总结

openfeign的自动配置过程逻辑相对比较简单,就是扫描了一下@FeignClient注解的接口,然后生成FeignClientFactoryBean的BeanDefinition给注册到容器当中。而具体的Bean对象,将会通过调用FeignClientFactoryBean的getObject方法来获取。

一、openfeign的自动配置的更多相关文章

  1. 企业IT管理员IE11升级指南【15】—— 代理自动配置脚本

    企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...

  2. 学记:为spring boot写一个自动配置

    spring boot遵循"约定优于配置"的原则,使用annotation对一些常规的配置项做默认配置,减少或不使用xml配置,让你的项目快速运行起来.spring boot的神奇 ...

  3. 网络连接详细信息出现两个自动配置ipv4地址

    问题:网络连接详细信息出现两个自动配置ipv4地址,一个是有效地址,一个是无效地址. 解决办法:先将本地连接ip设置成自动获取,然后点击开始——>运行——>输入cmd,回车,进入命令行界面 ...

  4. python环境变量自动配置脚本(setx使用)

    前言 setx不是windows系统自带的工具,需要到微软官网下载,但是有的系统也会自带.(是官方提供的,可放心食用) set和setx都可以用来配置环境变量.他们的不同点在于,set只是临时的修改环 ...

  5. 使用脚本自动配置matlab安装libsvm和随机森林工具箱

    前言 支持向量机(SVM)和随机森林 都是用于分类的机器学习算法. 这里我需要对网上的工具箱在matlab中进行配置. 效果演示: 1.双击运行“自动配置.bat” 2.matlab会自动启动,手动配 ...

  6. 转-IE浏览器自动配置代理脚本-Proxy.PAC文件及PAC相关语法

    用笔记本上网时,往返家里和单位,因为单位是用的代理上网,家里是直接连接.因此每次都要修改IE的代理设置,虽然是个小事,但是每次都要修改总是有点烦 ,于是参考GOOGLE,写了一个自动配置代理的脚本.这 ...

  7. Windows下Apache服务器中自动配置二级子域名

    今天我们介绍的这个办法,只需要简单修改 httpd-vhosts.conf 文件,配合 .htaccess 文件即可实现自动配置二级域名. 我们这里以 wpchina.com 为例,以下代码中的 wp ...

  8. [win]AD域组策略wifi自动配置

    http://wenku.baidu.com/link?url=MC950wliAZNeVUJ2M6Y1VTi5faqo7kG374fyBjW57r0qyLJkBZLg5ypiql4RFywQ8q7y ...

  9. spring boot实战(第十三篇)自动配置原理分析

    前言 spring Boot中引入了自动配置,让开发者利用起来更加的简便.快捷,本篇讲利用RabbitMQ的自动配置为例讲分析下Spring Boot中的自动配置原理. 在上一篇末尾讲述了Spring ...

随机推荐

  1. Docker Error response from daemon: driver failed programming external connectivity on endpoint webserver

    按照官网的配置, https://docs.docker.com/docker-for-windows/ 当执行到第 5 步时 如果当前你的电脑 80 端口已经被别的程序占用,运行以上命令就会报错,报 ...

  2. radioButon的使用

    界面: <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android=& ...

  3. openresty开发系列15--lua基础语法4表table和运算符

    openresty开发系列15--lua基础语法4表table和运算符 lua中的表table 一)table (表)Table 类型实现了一种抽象的"关联数组".即可用作数组,也 ...

  4. source insight 4.0常见问题及相关配置

    摘自:https://blog.csdn.net/liitdar/article/details/79891795     本文介绍source insight 4.0常见的问题以及相关的配置. 1. ...

  5. RabbitMQ 入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)

    发布/订阅 在上篇第二部分教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式 ...

  6. Sq常用操作

    sql创建表实例: CREATE TABLE mytable( id varchar(40) NOT NULL default '', userId varchar(40) NOT NULL defa ...

  7. 【443】Tweets Analysis Q&A

        [Question 01] When converting Tweets info to csv file, commas in the middle of data (i.e. locati ...

  8. docker build时改变docker中的apt源

    # Ali apt-get source.list RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak && \ echo & ...

  9. axios发了两次请求

    一.问题描述 用axios发post请求,却出现了options请求和post请求,options请求哪里来的? 二.问题分析 1.先温习一下跨域的知识 2.axios默认类型是Content-Typ ...

  10. ASP.NET全球化与本地化 c#多国语言的支持 (项目支持多国语言的开发)

    ASP.NET 2.0及以上的开发平台,为全球化本地化应用程序提供了工具,而且实现起来非常简单.以下内容是使用c#,按照帮助一步步做的,将为初学者提供详细的实现步骤. 一 几个必要概念 (一) 支持全 ...