ConfigurationClassPostProcessor
2024-02-01 15:29:27 6 举报
ConfigurationClassPostProcessor完成@Configuration的解析工作
作者其他创作
大纲/内容
parser.parse(candidates)
parse(Set<BeanDefinitionHolder> configCandidates)
postProcessBeanDefinitionRegistry回调处理流程
返回sourceClass是否为空
ImportSelector.selectImports
主要用于解析内部类。由于@Configuration注解也有@Component元注解,因此即使没有内部类也会进入该方法,此时就是空操作而已
是否存在@PropertySources、@PropertySource注解
如果是DeferredImportSelector子接口
递归调用processImports
将生成的代理类设置BeanDefinition的beanClass属性中beanDef.setBeanClass(enhancedClass);
如果没有前两个接口,则当做普通类,进行方法递归操作
ComponentScanAnnotationParser.parse扫描路径返回BeanDefinitionHolder
将configClass添加到ConfigurationClassParser的 configurationClasses集合中
如果是配置类
实例化当前类,并调用invokeAwareMethodsBeanClassLoaderAware#setBeanClassLoaderBeanFactoryAware#setBeanFactoryEnvironmentAware#setEnvironmentResourceLoaderAware#setResourceLoader
否
alreadyParsed.addAll(configClasses)已经加载完成,保存到集合中,避免重复解析
注解不为空&&conditionEvaluator.shouldSkip不会跳过
通过ComponentScan扫描之后,引入更多的类,这些类当中,可能存在更多的@Configuration配置类,因此需要递归解析
processConfigurationClass
从BeanFactory中获取所有的BeanDefinitionNames
非静态,非final,非private。也就是说除了静态方法不用校验外,其他方法只能是public类型的非final方法,也就是cglib能够重写的方法
是否是Configuration候选类
校验BeanMethod
2.deferredImportSelectorHandler.process()延迟处理(DeferredImportSelector)
添加CallbackFilterConditionalCallbackFilter
是
创建ConfigurationClassParser配置类解析器
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
返回
设置父类setSuperclass
遍历BeanDefinitionRegistry注册的BeanDefinitionName。与candidateNames、alreadyParsedClasses相比较,判断上述处理过程中,是否还有漏网的@Configuration配置类
总结:(1) 处理内部类,如果内部类也是一个配置类(判断一个类是否是一个配置类,通过ConfigurationClassUtils.checkConfigurationClassCandidate()可以判断)。(2) 处理属性资源文件,加了@PropertySource注解。(3) 首先解析出类上的@ComponentScan和@ComponentScans注解,然后根据配置的扫描包路径,利用ASM技术扫描出所有需要交给Spring管理的类,由于扫描出的类中可能也被加了@ComponentScan和@ComponentScans注解,因此需要进行递归解析,直到所有加了这两个注解的类被解析完成。(4) 处理@Import注解。通过@Import注解,有三种方式可以将一个Bean注册到Spring容器中。(5) 处理@ImportResource注解,解析配置文件。(6) 处理@Bean注解的方法。(7) 通过processInterfaces()处理接口的默认方法,从JDK8开始,接口中的方法可以有自己的默认实现,因此,如果这个接口中的方法也加了@Bean注解,也需要被解析。(很少用)(8) 解析父类,如果被解析的配置类继承了某个类,那么配置类的父类也会被进行解析doProcessConfigurationClass()(父类是JDK内置的类例外,即全类名以java开头的)
postProcessBeanDefinitionRegistry
跳过,继续循环
如果reader为空,则创建reader对象ConfigurationClassBeanDefinitionReader
调用deferredImportSelectorHandler.handler方法,进行延迟处理
是否包含CONFIGURATION_CLASS_ATTRIBUTE表示已经处理完毕
1. 判断BeanDefinition类型,走不同分支
parser.validate
实例化当前类,并调用invokeAwareMethods
处理父类,如果存在非java开头和非白名单中的父类,则返回父类类名,进行下一次循环
获取注解的location和reader
如果是EnhancedConfiguration实现类,表明已经是代理类,直接返回
do/while循环
processMemberClasses
向BeanFactory中添加一个BeanPostProcessorImportAwareBeanPostProcessor
递归调用processConfigurationClass
解析name、encoding、value、factory
for循环遍历scannedBeanDefinitions
保存到ConfigClass的beanMethods属性中
循环判断是否是配置类&&与父类类名不一样添加到candidates集合中
移除掉已经解析完成的的配置类alreadyParsed
configCandidates创建空集合,用来存在候选配置类BeanDefinition
是否存在@Component注解
是否存在@ImportResource注解
是否存在@Import注解
命名策略SpringNamingPolicy
已处理,跳过
getMemberClasses
递归调用parse方法
循环遍历BeanDefinitionName集合
doProcessConfigurationClass
如果获取到的属性值为full,则添加到configBeanDefs集合中,后续进行代理类创建
该注解与@PropertySource的区别1. @ImportResource用于支持spring配置文件,即在某些条件下引入额外的bean定义2.@PropertySource用于引入属性配置,只要用于JavaBean的装配
如果是ImportSelector实现类
添加接口setInterfacesEnhancedConfiguration
将实例对象保存到ConfigurationClass类的importBeanDefinitionRegistrars属性中。由于ConfigurationClass会在之后保存到ConfigurationClass属性中,最后进行方法回调
保存resource和readerClass到ConfigClass的属性中
添加到configCandidates集合中
从BeanDefinition中获取名称为org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass属性
conditionEvaluator.shouldSkip
parser.getConfigurationClasses()获取parser在解析过程中,引入新的配置类。主要是@ComponentScan和@Import引入。将返回值保存到configClasses集合中
是否存在@ComponentScans、@ComponentScan注解
reader.loadBeanDefinitions(configClasses)加载BeanDefinition
@Bean方法转换为BeanMethod对象
是否存在@Bean注解
循环
配置类不能为final,除非不需要被代理
processImports
processConfigBeanDefinitions(registry)处理配置类的解析
递归调用
candidates候选集合不为空
如果是ImportBeanDefinitionRegistrar
postProcessBeanFactory回调处理流程
遍历BeanDefinitionName,获取BeanDefinition
如果是static方法,直接返回,无需校验
@Configuration类是否需要增强,生成代理类enhanceConfigurationClasses
processPropertySource
遍历importCandidates
循环遍历value值(配置文件的location),转换为PropertySource之后,添加到Environment中
enhancer.createClass()创建代理类
处理接口中@Bean注解的default方法
0 条评论
下一页
为你推荐
查看更多