@Import和spring.factories实现原理

本篇文章主要记录@Import和spring.factories实现原理,具体怎么用,可自行百度
demo地址(代码结构很简单,不做任何说明)

@Import

基本用法参考

spring.factories

基本用法参考

问题:为什么@Import和spring.factories能够实现自动配置?

下面列出关键流程代码:从run方法开始,中间代码省略

SpringApplication.run(ClientApplication.class);
	refresh()
		invokeBeanFactoryPostProcessors(beanFactory);
			invokeBeanFactoryPostProcessors()
				postProcessBeanDefinitionRegistry(registry)
					processConfigBeanDefinitions(registry);

processConfigBeanDefinitions(registry)关键代码

private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();

//code_1
do{
	parser.parse(candidates);//Set<BeanDefinitionHolder>
}while(!candidates.isEmpty());
			
//code_2
this.reader.loadBeanDefinitions(configClasses);//Map:configurationClasses 

code_1循环解析BeanDefinitionHolder,实际上调用processConfigurationClass()将解析的结果添加到configurationClasses(map)中,解析过程如下:

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		//多种解析方式
		parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
		parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
		parse(bd.getBeanClassName(), holder.getBeanName());
		//这是关联spring.factories的代码(后面再解释)
		this.deferredImportSelectorHandler.process();
	}
//其中parse流程
parse()
	processConfigurationClass()
		doProcessConfigurationClass()

doProcessConfigurationClass():里面处理多种配置类

// Recursively process any member (nested) classes first
// Process any @PropertySource annotations
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
// Process individual @Bean methods
// Process default methods on interfaces
//...

看看processImports()的第三个参数getImports(sourceClass),收集@Import注解类
在这里插入图片描述
processImports方法中,可以看到(ImportSelector.class,ImportBeanDefinitionRegistrar.class)就是@import三种实现方法类

在这里插入图片描述

关于spring.factories的实现原理,最终都会调用SpringFactoriesLoader.loadFactoryNames(),
如EnableAutoConfiguration流程:

  • @SpringBootApplication注解中携带@EnableAutoConfiguration注解
  • @EnableAutoConfiguration注解使用@Import(AutoConfigurationImportSelector.class)导入AutoConfigurationImportSelector
  • AutoConfigurationImportSelector有个内部类AutoConfigurationGroup,内部类中process()方法调用getAutoConfigurationEntry(annotationMetadata)使用SpringFactoriesLoader.loadFactoryNames()获取spring.factories中所有自动配置类
  • spring.factories中所有自动配置类缓存在Map<String, AnnotationMetadata> entries

到这里spring.factories自动配置类都缓存在map中,究竟是何时调用

现在我们将@Import和spring.factories联系起来:
在梳理@Import原理过程中parse()方法:this.deferredImportSelectorHandler.process()

process()
	handler.processGroupImports()
		grouping.getImports()
			this.group.process()//触发读取spring.factories中配置类,写入Map
			this.group.selectImports()//use map to do something

至此,@Import和spring.factories实现原理已经梳理完毕(后续无非就是拿到类信息,创建对象,不属于这里的范畴),希望能够帮助到读者


彩蛋1:上面是以EnableAutoConfiguration为例子研究spring.factoies,对于
ApplicationContextInitializer看看源码就会找到定义的Initializer

SpringApplication.run(ClientApplication.class)
	prepareContext()
		applyInitializers(context)

在这里插入图片描述

在这里插入图片描述


彩蛋2:为什么当我们引用第三方starter时,可以直接在yml配置一些参数呢,目前只知道,本当前项目的application.yml配置会覆盖第三方yml文件中的配置
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值