本篇文章主要记录@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文件中的配置