以上是 Spring 容器刷新时的几个关键步骤,在步骤二 invokeBeanFactoryPostProcessors() 中会调用所有已经注册的 BeanFactoryPostProcessor 进行处理 。此处调用也是有顺序的,优先会调用所有 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(),BeanDefinitionRegistryPostProcessor 是一个特殊的 BeanFactoryPostProcessor,然后再调用所有 BeanFactoryPostProcessor#postProcessBeanFactory() 。
ConfigurationClassPostProcessor 是 BeanDefinitionRegistryPostProcessor 的一个实现类,该类主要用来处理 @Configuration 注解标注的类 。我们用 @Configuration 标注的类会被 ConfigurationClassParser 解析包装成 ConfigurationClass 对象,然后再调用 ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass() 进行 BeanDefination 的注册 。
其中 ConfigurationClassParser 解析时会递归处理源配置类上的注解(@PropertySource、@ComponentScan、@Import、@ImportResource)、 @Bean 标注的方法、接口上的 default 方法,进行 ConfigurationClass 类的补全填充,同时如果该配置类有父类,同样会递归进行处理 。具体代码请看 ConfigurationClassParser#doProcessConfigurationClass() 方法
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)throws IOException {// Process any @PropertySource annotations// Process any @ComponentScan annotations// Process any @Import annotationsprocessImports(configClass, sourceClass, getImports(sourceClass), filter, true);// Process any @ImportResource annotations// Process individual @Bean methodsSet<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// Process default methods on interfacesprocessInterfaces(configClass, sourceClass);// Process superclass, if anyif (sourceClass.getMetadata().hasSuperClass()) {String superclass = sourceClass.getMetadata().getSuperClassName();if (superclass != null && !superclass.startsWith("java") &&!this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturn sourceClass.getSuperClass();}}// No superclass -> processing is completereturn null; }【这些不知道,别说你熟悉 Spring】1)parser.parse(candidates) 解析得到完整的 ConfigurationClass 对象,主要填充下图框中的四部分 。

文章插图

文章插图
2)this.reader.loadBeanDefinitions(configClasses) 根据框中的四部分进行 BeanDefination 的注册 。

文章插图
在上述 processImports() 过程中会将 DeferredImportSelector 的实现类放在 deferredImportSelectorHandler 中以便延迟到所有的解析工作完成后进行处理 。deferredImportSelectorHandler 中就存放了 AutoConfigurationImportSelector 类的实例 。process() 方法里经过几步走会调用到 AutoConfigurationImportSelector#getAutoConfigurationEntry() 方法上获取到自动装配需要的类,然后进行与上述同样的 ConfigurationClass 解析封装工作 。

文章插图

文章插图
代码层次太深,调用太复杂,建议自己断点调试源码跟一遍印象会更深刻 。
ApplicationContextInitializer 调用时机我们就以 SpringBoot 项目为例来看,在 SpringApplication 的构造函数中会进行 ApplicationContextInitializer 的初始化 。
经验总结扩展阅读
- 年纪大了,这些星座就喜欢看甜甜的恋爱
- 胸闷是什么感觉
- 虽然单身时花心,但这些星座一旦恋爱就十分专一
- 主动创造激情,这些星座的爱越来越有深度
- 跟前任碰到,这些星座会落落大方
- 哪些星座男在恋爱中吵架,永远不知道错哪了
- 重燃爱火,这些星座配对有可能分手后还会和好
- 爱情的阴沟里不知道翻了多少次船的星座
- 剑盾如何联网
- 爱情早已戒掉,这些星座只想做自己的王者
