ConfigurationClassPostProcessor 解析

本文详细探讨了Spring Boot中ConfigurationClassPostProcessor的作用和工作原理,它负责处理@Configuration注解的类,解析配置元数据,启动应用程序上下文的配置过程。通过了解这一核心组件,可以更好地掌握Spring Boot的内部机制。
ConfigurationClassPostProcessor
    在AnnotationConfigEmbeddedWebApplicationContext构造方法中创建
    在invokeBeanFactoryPostProcessors()步骤中执行
    接口主要实现了BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor 接口
    在启动的时候会先执行BeanDefinitionRegistryPostProcessor接口的方法postProcessBeanDefinitionRegistry
    再执行BeanFactoryPostProcessor接口的方法postProcessBeanFactory
只记录重点参数
postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)
	--> processConfigBeanDefinitions(BeanDefinitionRegistry)
		从BeanDefinitionRegistry中得到所有注册的beanDefinition
		这里就会得到步骤prepareContext()将new SpringApplication(AppBarrageRobotApplication.class)的AppBarrageRobotApplication加入到beanFactory中的AppBarrageRobotApplication
		进而可以扫描到启动类AppBarrageRobotApplication上面的注解
		--> checkConfigurationClassCandidate(BeanDefinition)
			找到所有包含Configuration Component ComponentScan Import ImportResource的BeanDefinition 或者有Bean注解的方法
			Configuration的bean会加上full标志
			其余的会标志lite标志
			加入configCandidates list集合

		--> 创建ConfigurationClassParser对象parser,用来解析上面的那些BeanDefinition集合configCandidates,这里将list转成了LinkedHashSet candidates

		--> parser.parse(candidates) while do 循环解析刚刚得到的BeanDefinition集合candidates,循环的原因是因为解析的过程中可能会有新的BeanDefinition包含那些注解 注意这里传进去的是整个集合
			遍历刚刚传进来集合的元素
				-->1 processConfigurationClass(ConfigurationClass configClass) ConfigurationClass是将注解信息与beanName封装在一起的对象 
				--> 根据configClass创建SourceClass 
				--> doProcessConfigurationClass(configClass,sourceClass)
					--> processMemberClasses(configClass, sourceClass) 处理内部类 调用processConfigurationClass()方法继续解析被发现的配置类
					--> ComponentScanAnnotationParser对象处理ComponentScans ComponentScan注解
						得到要扫描的包下面的类resource,过滤找到Component注解的类封装成ScannedGenericBeanDefinition集合
					    针对上一步得到的集合,遍历调用processConfigurationClass(ConfigurationClass)(上面第一步)
					
					--> processImports(...)处理Import注解
						实现了ImportSelector接口的话,如果还实现了DeferredImportSelector接口,就加入deferredImportSelectors集合,后面再执行;否则就执行selectImports方法
						得到被引入的类的集合,将集合重新执行processImports(...)处理Import注解

						如果实现了ImportBeanDefinitionRegistrar接口,那么就放入configClass的importBeanDefinitionRegistrars中,等待后续处理

						以上都不是的话说明引入的是普通bean,调用第一步的processConfigurationClass递归执行

					--> 处理ImportResource注解,将解析出啦的资源放入configClass的importedResources中,等待后续处理

					--> 处理带有Bean注解的方法,封装成MethodMetadata放入configClass的beanMethods中,等待后续处理
				
				--> 将刚刚处理过的ConfigurationClass放入ConfigurationClassParser对象parser的configurationClasses中
			
			--> processDeferredImportSelectors() 处理刚刚加入deferredImportSelectors集合的DeferredImportSelector实现类
				遍历执行selectImports方法,得到被引入的类的集合,将集合重新执行processImports(...)处理Import注解
		
		--> parser.validate() 校验刚刚configurationClasses集合中的对象 如果有Configuration注解,那么就要能被继承和被重写(不能是final类型的类)

		--> 通过ConfigurationClassBeanDefinitionReader对象的loadBeanDefinitions(configurationClasses)方法将刚刚parser的configurationClasses集合全部注册到beanFactory中beanDefinitionMap
	
				
postProcessBeanFactory(beanFactory)
	--> enhanceConfigurationClasses(beanFactory) 采用cglib给注解了Configuration的做代理(主要原因 对调用有Bean注解的方法进行代理,让其多次调用只生成一次对象,返回一个单例对象 以及处理 factoryBean相关东西)
		方法拦截类有BeanMethodInterceptor BeanFactoryAwareMethodInterceptor 两个
			BeanMethodInterceptor 
				 第一个条件,不能是Object,这个必定是满足的
				 第二个条件,不能是setBeanFactory方法,显而易见的嘛,我们要拦截的方法实际只应该是添加了Bean注解的方法
				 第三个条件,添加了Bean注解
					对调用有Bean注解的方法进行代理,让其多次调用只生成一次对象,返回一个单例对象 以及处理 factoryBean相关东西
			BeanFactoryAwareMethodInterceptor 
				在调用setBeanFactory方法时才会拦截 
					代理类中添加一个字段,BEAN_FACTORY_FIELD = "$$beanFactory" 并设置beanFactory
	--> 向beanFactory中添加ImportAwareBeanPostProcessor

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值