OpenFeign
OpenFeign 是一个声明式 RESTful 网络请求客户端。OpenFeign 会根据带有注解的函数信息构建出网络请求的模板,在发送网络请求之前,OpenFeign 会将函数的参数值设置到这些请求模板中。虽然 OpenFeign 只能支持基于文本的网络请求,但是可以极大简化网络请求的实现,方便快速构建自己的网络请求应用。
OpenFeign 的 Spring 应用架构一般分为三部分,分别为注册中心,服务提供者和服务消费者。服务提供者向服务注册中心注册自己,然后服务消费者通过 OpenFeign 发送请求时,OpenFeign 会向服务注册中心获取关于服务提供者的信息,然后再向服务提供者发送网络请求。
消费者添加 @EnableFeignClients 开启 Spring Cloud OpenFeign 的自动化配置功能
@EnableFeignClients 就像一个开关,只有使用了该注解,OpenFeign 相关的组件和配置机制才会生效。
源码分析
FeignClientFactoryBean 是创建 @FeignClient 修饰的接口类 Bean 实例的工厂类,FeignContext 是配置组件的上下文环境,保存着相关组件的不同实例,这些实例由不同的 FeignConfiguration 配置构造出来,SynchronousMethodHandler 是 MethodHandler 的子类,可以在 FeignClient 相应方法被调用时发送网络请求,然后再将请求响应转化为函数返回值进行输出。
OpenFeign 会首先进行相关 BeanDefinition 的动态注册,然后当 Spring 容器注入相关实例时会进行实例的初始化,最后当 FeignClient 接口实例的函数被调用时会发送网络请求。
动态注入 BeanDefinition
@EnableFeignClients 三个作用:
引入 FeignClientsRegistrar
指定 FeignClient 的包信息,也就是指定 FeignClient 接口类所在的包名
指定 FeignClient 接口类的自定义配置类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
* declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
* {@code @ComponentScan(basePackages="org.my.pkg")}.
* @return the array of 'basePackages'.
*/
String[] value() default {};
/**
* Base packages to scan for annotated components.
* <p>
* {@link #value()} is an alias for (and mutually exclusive with) this attribute.
* <p>
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
* package names.
* @return the array of 'basePackages'.
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return the array of 'basePackageClasses'.
*/
Class<?>[] basePackageClasses() default {};
/**
* A custom <code>@Configuration</code> for all feign clients. Can contain override
* <code>@Bean</code> definition for the pieces that make up the client, for instance
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
*
* @see FeignClientsConfiguration for the defaults
* @return list of default configurations* A custom <code>@Configuration</code> for all feign clients. Can contain override
* <code>@Bean</code> definition for the pieces that make up the client, for instance
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
*
* @see FeignClientsConfiguration for the defaults
* @return list of default configurations
*/
Class<?>[] defaultConfiguration() default {};
/**
* List of classes annotated with @FeignClient. If not empty, disables classpath
* scanning.
* @return list of FeignClient classes
*/
Class<?>[] clients() default {};
}
复制代码
FeignClientsRegistrar 是 ImportBeanDefinitionRegistrar 的子类,Spring 用 ImportBeanDefinitionRegistrar 来动态注册 BeanDefinition。OpenFeign 通过 FeignClientsRegistrar 来处理 @FeignClient 修饰的 FeignClient 接口类,将这些接口类的 BeanDefinition 注册到 Spring 容器中,这样就可以使用 @Autowried 等方式自动装载这些 FeignClient 接口类的 Bean 实例。
❤️ 感谢大家
如果你觉得这篇内容对你挺有有帮助的话:
欢迎关注我❤️,点赞👍🏻,评论🤤,转发🙏
关注盼盼小课堂
,定期为你推送好文,还有群聊不定期抽奖活动,可以畅所欲言,与大神们一起交流,一起学习。
评论