Feign 从注册到调用原理分析

本文详细解析了Feign如何注册到Spring容器,包括@FeignClient的注册过程,如扫描BeanDefinition,创建FeignClient的代理对象。同时,文章探讨了Feign的调用流程,涉及FeignInvocationHandler、LoadBalancerFeignClient和Ribbon的负载均衡。通过分析,揭示了Feign如何整合Ribbon获取注册中心服务并进行负载均衡选择。
摘要由CSDN通过智能技术生成

在这里插入图片描述

在这里插入图片描述本文主要讲述 Feign 是如何注册到 Spring 容器、融合 Ribbon进行负载均衡、进行 RPC 调用。

简单提一下项目中一般都是如何使用 Feign 的,首先声明一个@FeignClient定义 RPC 调用方法,然后像调用本地方法一样,调用远程服务的方法

// 定义 FeignClient 
@FeignClient(value = "service-order",path = "/order") 
public interface OrderFeignService {
    

	@RequestMapping("/findOrderByUserId/{userId}") 
	R findOrderByUserId(@PathVariable("userId") Integer userId); 
} 
// 调用远程服务 
@Autowired 
OrderFeignService orderFeignService; 

R findOrderByUserId(@PathVariable("id") Integer id) {
    
	//feign调用 
	R result = orderFeignService.findOrderByUserId(id); 
	return result; 
} 

这样一来,我们省去了自己去配置 RestTemplate 或其他 HTTPClient 的麻烦,但是简单方便的同时你是否会有一些疑惑:

我们使用@Autowired注入的 OrderFeignService,那么它一定是一个 Spring Bean,它是什么时候,如何被注入到 Spring 容器的?

  • Feign 是如何执行 findOrderByUserId()的?
  • @RequestMapping 是 SpringMVC 的注解呀,怎么在 Feign 中也会生效呢?
  • Feign 是如何整合 Ribbon 的?
  • Ribbon 是如何获取注册中心的服务的?
  • Ribbon 是如何进行负载均衡的?

理解了上面的这些问题,我们也就明白了 Feign 是如何进行调用的,那么带着这些问题我们来一步步分析

@FeignClient 注册

@EnableFeignClients 注解

根据 SpringBoot 自动装配的思想,先猜想下一定会有@Enablexxx ,然后再有@Import(xxx.class),来进行 Feign 的自动注入

要使用 Feign 首先要

  1. 引入 Feign 的 Maven 依赖,接着一定要在启动类上添加注解 @EnableFeignClients
  2. @EnableFeignClients @Import(FeignClientsRegistrar.class)
  3. 注册 @FeignClient

在这里插入图片描述

在这里插入图片描述

FeignClientsRegistrar.class

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   
        this.registerDefaultConfiguration(metadata, registry);
        this.registerFeignClients(metadata, registry);
    }

1. 扫描并注册 FeignClient 为 BeanDefinition

public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    
	// ...,省略了部分源码 
	扫描所有 @FeignClient 标注的类 
	Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName()); 
	AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter( FeignClient.class); 
	// ... 
	for (String basePackage : basePackages) {
    
	// ... 
	Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName()); 
	// ... 
	// 注册 FeignClient 为 BeanDefinition 
	registerFeignClient(registry, annotationMetadata, attributes); 
} } } 

2. 将 FeignClient 包裹成 FeignClientFactoryBean

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, 
Map<String, Object> attributes) {
    

	String className = annotationMetadata.getClassName(); 
	// 将 FeignClient 包裹成 FeignClientFactoryBean 
	BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class); // ... 一堆definition.addPropertyValue() 
	definition.addPropertyValue("fallbackFactory",attributes.get("fallbackFactory")); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); 
	// ... 
	// 注册 
	FeignClientFactoryBean BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[] {
    alias }); 
	BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); 
} 

3. FeignClientFactoryBean#getObject(),生成FeignClient 的代理对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值