ConfigurationClassPostProcessor执行过程解析
2021-04-12 09:34:08 0 举报
ConfigurationClassPostProcessor执行过程解析
作者其他创作
大纲/内容
后续获取到parser.getConfigurationClasses() 并在loadBeanDefinitions中解析
scanCandidateComponents
处理之前@bean注解解析出来的beanMethod集合
getResourcePatternResolver().getResources(packageSearchPath)
processImports
处理ImportedResources注册进来的集合
找到package下符合的类
loadBeanDefinitionsForConfigurationClass的registerBeanDefinitionForImportedConfigurationClass解析注册
在refresh()方法的invokeBeanFactoryPostProcessors中会执行注册好的6个基础类的BeanFactoryPostProcessors方法,其中有一个非常重要的解析配置类的processors就是ConfigurationClassPostProcessor
解析所有@Import注解
ImportSelector,它需要返回需要导入的组件的全类名数组。asSourceClasses方法会将全类名通过反射的方法转化为class再次调用processImports,注意这一次如果是普通的类就不会再走这个分支了,会走到else分支,当作一个配置类解析,并注册
processConfigBeanDefinitions
ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern;
scanner.doScan(StringUtils.toStringArray(basePackages))
loadBeanDefinitionsForConfigurationClass
处理除了上面两种方式的,分析ImportSelector也会知道里面的类实例化之后就会调用到这个分支
loadBeanDefinitionsFromRegistrars
获取到selector返回的全类名的数组selector.selectImports(currentSourceClass.getMetadata())
for configClass.getBeanMethods()执行loadBeanDefinitionsForBeanMethod(beanMethod)
processConfigurationClass(candidate.asConfigClass(configClass))
对于ImportBeanDefinitionRegistrar来说我们最终的仅仅是在importBeanDefinitionRegistrars这个map中put一个类,并没有直接进行注册操作。真实的注册操作会在后面的reader.loadBeanDefinitions(configClasses)
构造了一个parse后面做解析
对于BeanDefinitionRegistryPostProcessor来说是继承了BeanFactoryPostProcessor方法的。所以需要同时执行postProcessBeanDefinitionRegistry和postProcessBeanFactory方法
这里面会判断去除包含在excludeFilters还有不包含在includeFilters的数据
处理@Bean和default methods
candidate.isAssignable(ImportBeanDefinitionRegistrar.class)
configClass.addBeanMethod
将解析完成的类放到这个classes中
将之前获取的方法加入beanMethods集合里面
再次调用processImports,传入刚转化出来的class
loadBeanDefinitionsForBeanMethod
else
循环执行loadBeanDefinitionsForConfigurationClass
超级重要的一个方法
candidate.isAssignable(ImportSelector.class)
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars())
findCandidateComponents(basePackage)
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
这个方法的内部判断当前的类是否是1.isFullConfigurationCandidate(标注了Configuration的配置类)2.isLiteConfigurationCandidate(标注了@Component,@ComponentScan,@Import,@ImportResource的类)只有上述两种类才被认为是一个config类
从这里正式进入ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
ComponentScanAnnotationParser.parse
处理@ComponentScans
asSourceClasses(importClassNames)
处理ImportSelector
configClass.addImportBeanDefinitionRegistrar
转化为class
parser.parse
获取标注了@Bean的方法
放到configurationClasses中保存
invokeBeanFactoryPostProcessors
registry.registerBeanDefinition
获取路径下符合的class
大体逻辑就是使用package拼接一个扫描路径:com.suncl --> classpath*:com/suncl/**/*.class之后扫描到路径下所有的class文件
getImportBeanDefinitionRegistrars就是获取之前放置到map的数据
我们会走到AnnotatedBeanDefinition的分支
loadBeanDefinitionsFromImportedResources
parse后会返回扫描到的注册的bean,并循环当前bean的class,递归解析加载
处理@ImportResource
Spring Boot 官网使用的是application.properties文件来实现文件的配置。但是实际情况下一个配置文件是不够用的,比如项目集成redis,mq,以及数据库比如mysql的时候,多个配置文件有利于开发及维护的管理。Spring Boot是通过@PropertySource或者@PropertySources来实现多配置文件的
解析import
处理@PropertySources
retrieveBeanMethodMetadata(sourceClass)
获取config配置类
执行postProcessBeanFactory方法
处理ImportBeanDefinitionRegistrar
@ImportResource注解用于导入Spring的配置文件,让配置文件里面的内容生效;(就是以前写的springmvc.xml、applicationContext.xml)
获取已经注册的BeanDefinitionRegistryPostProcessor
循环处理Resource
isCandidateComponent
处理之前importBeanDefinitionRegistrars注册进来的集合
ConfigurationClassUtils.checkConfigurationClassCandidate
执行BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
configurationClasses的数据在这里不会直接解析,后面loadBeanDefinitions统一解析
执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
处理@Component
处理@Import
reader.loadBeanDefinitions(configClasses)
这里存在一个优先级判断,实现PriorityOrdered接口的 > 实现Ordered接口的 > 未实现上面两个接口的 (BeanDefinitionRegistryPostProcessor实现了PriorityOrdered第一批次执行)
getImports(sourceClass)
处理之前 importSelector导入进来的数据 importedBy不是空
对于@bean的方法到这里就暂时结束了,后面等到reader.loadBeanDefinitions的时候统一解析
ConfigurationClassParser.processConfigurationClass
找到带有ComponentScans注解的类
new ConfigurationClassParser所有的解析都依托于这个parse
ConfigurationClassPostProcessor.invokeBeanFactoryPostProcessors
老样子这里存在一个优先级判断,实现PriorityOrdered接口的 > 实现Ordered接口的 > 未实现上面两个接口的
拼接扫描路径
获取已经注册的BeanFactoryPostProcessor
依旧是一个很重要的方法前面放置到map没有注册的类都在这里完成真正的注册
registerBeanDefinitionForImportedConfigurationClass
实现了DeferredImportSelector接口的会延迟执行 这里就不讨论延迟导入了
0 条评论
下一页