Spring Cloud Feign【源码篇】Feign 如何进行服务间请求调用

参考资料:
Spring Cloud 官网
相关版本:Spring Boot 2.1.5 、 spring cloud Greenwich.SR1
spring-cloud-openfeign 2.1.1

Spring Cloud Feign 默认使用 HTTP 的形式进行远程服务调用。

先来看一个简单的案例,假设此时有一个服务provider 和一个服务consumer。

服务provider 9527 提供接口/hello/{name}
服务consumer 9528 调用 服务provider的 hello/{name} 接口

服务consumer 通过 RestTemplate 发起 HTTP 请求调用服务 provider 接口代码如下:

@RequestMapping("/feign/hello/{param}")
public Object hello(@PathVariable String param,) throws InterruptedException {
   
	return  restTemplate.getForObject("http://localhost:9527/hello/" + param,String.class);
}

在上面代码中,我们通过传入一个字符参数,发起 http 请求,接收一个字符串的返回结果。

假设,此时我们需要传入的是一个对象,对象中存在多个参数,返回结果同样也是一个对象。
这时候,为了能够提高开发效率,我们就需要对 RestTemplate 进行封装,例如,通过反射获取参数对象值,并进行拼接,返回结果同样需要通过反射进行赋值等。

而 Feign 帮我们对 RestTemplate 进行了封装,除此之外,Feign 集成了 Hystrix ,Ribbon 等功能。在之后会针对 Feign 对 Hystrix 和 Ribbon 等集成进行分析。

Feign 简单例子

**step1、**引入依赖

**step2、**开启 Feign 功能
@EnableFeignClients

**step3、**编写相关代码,如下图
在这里插入图片描述
总结:使用 Feign 进行远程调用,只需定义一个 Feign 客户端,通过调用方法的形式,便可完成远程接口调用。

Feign Client 如何被加载到 Spring 中

在上面 Feign 调用的案例中 HelloClient 只需 @FeignClient 注解,然后 @Autowired 进行注入便可完成 Feign Client 注入。

下面通过源码分析,看看 Feign Client 是如何被加载到 Spring 中的。

Feign Client BeanDefinition 信息注册

以 @EnableFeignClients 为入口,进行源码分析

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
   
}

通过 EnableFeignClients 源码查看,聚焦 @Import(FeignClientsRegistrar.class) 中的 FeignClientsRegistrar.class。

FeignClientsRegistrar

FeignClientsRegistrar 类实现了 ImportBeanDefinitionRegistrar 。聚焦 FeignClientsRegistrar#registerBeanDefinitions 方法。

知识点:实现了 ImportBeanDefinitionRegistrar 的类,会根据该类的配置属性进行相关 Bean 的动态注入。

FeignClientsRegistrar#registerBeanDefinitions

class FeignClientsRegistrar
		implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
   
	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
   
		// 注册 EnableFeignClients 中配置的相关到 BeanDefinitionRegistry 中
		registerDefaultConfiguration(metadata, registry);
		// 注册 Feign 客户端到 BeanDefinitionRegistry 中
		registerFeignClients(metadata, registry);
	}

方法中调用了两个方法

  • registerDefaultConfiguration(metadata, registry);
    该方法主要是获取注解 @EnableFeignClients 中是否有相关的配置信息,如果有进行配置信息的注册

  • registerFeignClients(metadata, registry);
    该方法是用来将我们定义的带有 @FeignClient 注解的类注册到 BeanDefinitionRegistry 中

追踪主线方法 registerFeignClients(metadata, registry);

FeignClientsRegistra#registerFeignClientsr

class FeignClientsRegistrar
		implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
   
	public void registerFeignClients(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
   

		// 定义过滤条件,需要包含 FeignClient 
		AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
				FeignClient.class);

		scanner.addIncludeFilter(annotationTypeFilter);

		// 获取扫描的包
		basePackages = getBasePackages(metadata);

		for (String basePackage : basePackages) {
   
			// 根据包路径,过滤条件,获取相关类的 BeanDefinition 
			Set<BeanDefinition> candidateComponents = scanner
					.findCandidateComponents(basePackage);
			for (BeanDefinition candidateComponent : candidateComponents) {
   
				if (candidateComponent instanceof AnnotatedBeanDefinition) {
   
					// 如果每个 FeignClient 有相关的配置,则进行配置注入
					registerClientConfiguration(registry, name,attributes.get("configuration"));

					// 进行 Feign Client 注入
					registerFeignClient(registry, annotationMetadata, attributes);
				}
			}
		}
	}
}

处理逻辑

1、获取所有需要扫描的包路径。
该路径可以从 EnableFeignClients 中的配置中获取,如:value,basePackages,basePackageClasses。
如果 EnableFeignClients 中没有进行配置,默认扫描包路径为:应用 @EnableFeignClients 的类,也就是 Application 启动类所在包路径为主。
例如:com.qguofeng.Application.class 启动类 中 @EnableFeignClients 中没有相关扫描包配置时,则默认扫描 FeignClient 的路径为:com.qguofeng

2、增加扫描条件
在 步骤 1 中确定了需要扫描的包路径,为了获取精确数据,增加筛选条件:

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值