内置后置PostPocess处理器

配置类进行解析的过程

注解加载过程

在执行代码 this.reader = new AnnotatedBeanDefinitionReader(this);的时候就会往BeanDefinitionMap注册ConfiguarationClassPostProcessor(用于注册配置类的处理器),还会去注册很多其他的用于注解的bean定义(例如解析@Autowired)

下一句代码的this.scanner = new ClassPathBeanDefinitionScanner(this);创建出来的scanner对象并没有在解析@compennt、配置类的时候用,只是提封装在了context对象中供后续手动调用,例如一开始没有指定配置类,后续可以手动扫描指定的类,目前这个new出来的scanner没有实质的作用。

接着执行this.reader.register(annotatedClasses);这里会把配置类(例如是加了@Configuration注解的MainConfig)注册进beandefinitionMap,那么这时候beandefinitionMap中既有了解析配置类的处理器也有了配置类,就可以开始准备解析配置类了。那么就可以执行refresh方法中的invokeBeanFactoryPostProcessors(beanFactory);

invokeBeanFactoryPostProcessors(beanFactory)

在这里会执行所有实现了bean工厂的后置处理器。

首先会执行

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

这里传入bean工厂和获取applicationContext中的bean工厂后置处理器(但是由于没有任何实例化过程,所以传递进来的为空)。

在这个方法里面,因为传递进来的beanFactoryPostProcessors为空,所以直接进行下面的步骤:第一步:去bean定义容器中获取BeanDefinitionRegistryPostProcessor的bean的处理器名称,其实也就是去获取解析配置类的后置处理器ConfiguarationClassPostProcessor。

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

接着会判断是否实现了表示最优先调用的接口priorityOrdered, ConfiguarationClassPostProcessor是实现了。

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//显示的调用getBean()的方式获取出该对象然后加入到currentRegistryProcessors集合中去
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//同时也加入到processedBeans集合中去
					processedBeans.add(ppName);
				}

如果是,则会放入集合currentRegistryProcessors,代表即将准备调用的后置处理器。在对这些处理器进行排序之后会放入总的队列中,进行调用

//对currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor进行排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//把他加入到用于保存到registryProcessors中
			registryProcessors.addAll(currentRegistryProcessors);
			/**
			 * 在这里典型的BeanDefinitionRegistryPostProcessor就是ConfigurationClassPostProcessor
			 * 用于进行bean定义的加载 比如我们的包扫描,@import  等等。。。。。。。。。
			 */
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

调用完之后会与之前类似,依次去调用实现了ordered、没有实现任何优先级接口的、既实现了bean工厂的后置处理器又实现了带注册功能的bean工厂后置处理器。最后一个如果即实现了带注册功能的bean工厂后置处理器又实现了bean工厂后置处理器那么他就会调用两次。

 ConfiguarationClassPostProcessor会在1、4都进行一次调用。其中在第四次调用中会去执行自身的postProcessBeanFactory方法,并且使用cglib对配置类进行了动态代理。

对配置类进行动态代理是因为把@bean的属性都注册进IOC容器,否则每次都要新创建对象,就不是面向IOC的了。动态代理之后每次都会先根据方法名去getBean(),如果IOC容器里面有就会先从IOC容器里面拿,不用重复创建对象。这也是配置类需不需要加@Configuration注解的重要区别了,spring会对加了@Configuration的配置类进行cglib动态增强

第一次调用 ConfiguarationClassPostProcessor后置处理器

在这里会真正的解析bean定义。

首先会去判断哪些类是正式的配置类(带有@configuration注解)哪些类不是正式的配置类,在beandefinitionMap中获取到配置类

//获取IOC 容器中目前所有bean定义的名称
		String[] candidateNames = registry.getBeanDefinitionNames();

		//循环我们的上一步获取的所有的bean定义信息
		for (String beanName : candidateNames) {
			//通过bean的名称来获取我们的bean定义对象
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			//判断是否有没有解析过
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			//进行正在的解析判断是不是完全的配置类 还是一个非正式的配置类
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				//满足添加 就加入到候选的配置类集合中
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

拿到配置类之后就开解析配置类:

//创建一个配置类解析器对象
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//真正的解析我们的配置类
			parser.parse(candidates);

真正执行的是doProcessConfigurationClass()方法,在这里面会去解析@ComponentScan、@Import、@Bean等。

以解析@ComponentScan为例

//从我们的配置类上解析处ComponentScans的对象集合属性
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			//循环解析 我们解析出来的AnnotationAttributes
			for (AnnotationAttributes componentScan : componentScans) {
				//把我们扫描出来的类变为bean定义的集合 真正的解析,注册bean定义
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				//循环处理我们包扫描出来的bean定义
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					//判断当前扫描出来的bean定义是不是一个配置类,若是的话 直接进行递归解析
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						//递归解析
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值