配置类进行解析的过程
注解加载过程
在执行代码 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());
}
}
}
}