Feign源码解析之生成jdk动态代理

Feign源码解析之注入IOC容器

上一篇中我们已经提到,对于被@FeignClients注解的接口,我们会根据其属性在IOC容器里注入一个FeignClientFactoryBean,而FeignClientFactoryBean实现了FactoryBean接口,因此实际上我们对该bean进行初始化后得到的是其getObject的返回值。这也是我们能够通过类似于调用服务的方法实现http请求发送的关键所在。
在了解getObject之前,我们先看一下FeignAutoConfiguration类,可以看出这是一个自动配置类。关于自动配置的内容可以通过EnableAutoConfiguration源码解析参考了解。
在FeignAutoConfiguration里通过@bean往IOC容器里注入了不少的bean,我们先了解一下FeignContext类,这是实现feign的一个相当关键的类。

@Configuration
@ConditionalOnClass(Feign.class)
@EnableConfigurationProperties({FeignClientProperties.class, FeignHttpClientProperties.class})
public class FeignAutoConfiguration {

	@Autowired(required = false)
	private List<FeignClientSpecification> configurations = new ArrayList<>();

	//省略其它方法

	@Bean
	public FeignContext feignContext() {
		FeignContext context = new FeignContext();
		context.setConfigurations(this.configurations);
		return context;
	}
}

进入feignContext类,该类是泛型类NamedContextFactory的子类,除了构造方法外没有其它的额外属性和方法。

public class FeignContext extends NamedContextFactory<FeignClientSpecification> {

	public FeignContext() {
		super(FeignClientsConfiguration.class, "feign", "feign.client.name");
	}
}

接着点击super方法进入NamedContextFactory类,构造方法中初始化了defaultConfigType 、propertySourceName 和 propertyName 的属性值。

public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName,
		String propertyName) {
	this.defaultConfigType = defaultConfigType;
	this.propertySourceName = propertySourceName;
	this.propertyName = propertyName;
}

接着看setConfigurations方法,可以看出其将IOC容器中的所有FeignClientSpecification类以其name属性为key值组成了Map结构,并作为configurations 属性。

private Map<String, C> configurations = new ConcurrentHashMap<>();

public void setConfigurations(List<C> configurations) {
	for (C client : configurations) {
		this.configurations.put(client.getName(), client);
	}
}

除此之外,我们还应该注意到NamedContextFactory类实现了ApplicationContextAware接口,并将当前的spring上下文applicationContext设置为parent属性。
另外,NamedContextFactory类还有一个极其重要的属性contexts,feign中的每一个client对应AnnotationConfigApplicationContext,contexts的key值就是client的name值,这一点和configurations的key值吻合。

private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();

getContext作为根据client的name获取applicationContext值的方法,和其它从缓存里获取值的方法没有什么区别。先判断缓存是否存在,如果不存在将生成对应的context并放入缓存,然后从缓存里进行获取。

protected AnnotationConfigApplicationContext getContext(String name) {
	if (!this.contexts.containsKey(name)) {
		synchronized (this.contexts) {
			if (!this.contexts.containsKey(name)) {
				this.contexts.put(name, createContext(name));
			
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值