Spring ConfigurationClassPostProcessor Bean解析及自注册过程
一、Bean的自注册过程

二、自注册过程说明
ConfigurationClassParser解析流程
1、处理@PropertySources注解,配置信息的解析
2、处理@ComponentScan注解:使用ComponentScanAnnotationParser扫描basePackage下的需要解析的类(@SpringBootApplication注解也包括了@ComponentScan注解,只不过basePackages是空的,空的话会去获取当前@Configuration修饰的类所在的包[这个会在下面详细解释]),并注册到BeanFactory中(这个时候bean并没有进行实例化,而是进行了注册。具体的实例化在finishBeanFactoryInitialization方法中执行)。对于扫描出来的类,递归解析
3、处理@Import注解:先递归找出所有的注解,然后再过滤出只有@Import注解的类,得到@Import注解的值。比如查找@SpringBootApplication注解的@Import注解数据的话,首先发现@SpringBootApplication不是一个@Import注解,然后递归调用修饰了@SpringBootApplication的注解,发现有个@EnableAutoConfiguration注解,再次递归发现被@Import(EnableAutoConfigurationImportSelector.class)修饰,还有@AutoConfigurationPackage注解修饰,再次递归@AutoConfigurationPackage注解,发现被@Import(AutoConfigurationPackages.Registrar.class)注解修饰,所以@SpringBootApplication注解对应的@Import注解有2个,分别是@Import(AutoConfigurationPackages.Registrar.class)和@Import(EnableAutoConfigurationImportSelector.class)。找出所有的@Import注解之后,开始处理逻辑:
(1)、遍历这些@Import注解内部的属性类集合
(2)、如果这个类是个ImportSelector接口的实现类,实例化这个ImportSelector,如果这个类也是DeferredImportSelector接口的实现类,那么加入ConfigurationClassParser的deferredImportSelectors属性中让第6步处理。否则调用ImportSelector的selectImports方法得到需要Import的类,然后对这些类递归做@Import注解的处理
(3)、如果这个类是ImportBeanDefinitionRegistrar接口的实现类,设置到配置类ConfigurationClass的importBeanDefinitionRegistrars属性中
(4)、其它情况下把这个类入队到ConfigurationClassParser的importStack(队列)属性中,然后把这个类当成是@Configuration注解修饰的类递归重头开始解析这个类
4、处理@ImportResource注解:获取@ImportResource注解的locations属性,得到资源文件的地址信息。然后遍历这些资源文件并把它们添加到配置类的importedResources属性中
5、处理@Bean注解:获取被@Bean注解修饰的方法,然后添加到配置类的beanMethods属性中
6、处理DeferredImportSelector:处理第3步@Import注解产生的DeferredImportSelector,进行selectImports方法的调用找出需要import的类,然后再调用第3步相同的处理逻辑处理
@SpringBootApplication注解
@SpringBootApplication注解被@EnableAutoConfiguration修饰,@EnableAutoConfiguration注解被@Import(EnableAutoConfigurationImportSelector.class)修饰,所以在第3步会找出这个@Import修饰的类EnableAutoConfigurationImportSelector,这个类刚好实现了DeferredImportSelector接口,接着就会在第6步被执行。第6步selectImport得到的类就是自动化配置类。
EnableAutoConfigurationImportSelector的selectImport方法会在spring.factories文件中找出key为EnableAutoConfiguration对应的值【这些值就是所谓的自动化配置类(XXXAutoConfiguration)】。
ConfigurationClassParser解析完成之后,被解析出来的类会放到configurationClasses属性中。然后使用ConfigurationClassBeanDefinitionReader去解析这些类。
ComponentScanAnnotationParser包扫描相关
首先启动一个springboot web工程,找到ApplicationContext的父类org.springframework.context.support.AbstractApplicationContext

我们发现,其真实的对象的类型是AnnotationConfigEmbeddedWebApplicationContext。 自身构造过程如下。

继续追踪AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)


终于找到了ConfigurationClassPostProcessor自注册后置处理器。这里有个有趣的ConfigurationClassPostProcessor解析流程, 内部调用中会使用 ComponentScanAnnotationParser去扫描,ComponentScanAnnotationParser类的parse方法有这样一段逻辑
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
参考下面的相关图:
也就是如果basePackages没有配置,会找declaringClass 对应包及其子包,declaringClass对应springboot项目中我们写的Application.java(@SpringBootApplication)




调用栈

实际项目结构

包结构这样的话,即使不配置componentScan,不使用AutoConfiguration,也可以扫描到bean。Application.java带有@SpringbootApplication注解,该注解中带有@ComponentScan注解,Application.java包的范围包含了所有java文件,所以项目中所有bean都可以被扫描到。
注:declaringClass 指的是带有@ComponentScan 注解的类
欢迎访问微信订阅号原文:ConfigurationClassPostProcessor Bean解析及自注册过程
就先分享这么多了,更多分享请关注我们的技术公众吧!!!
Spring ConfigurationClassPostProcessor Bean解析及自注册过程的更多相关文章
- Spring源码解析之:Spring Security启动细节和工作模式--转载
原文地址:http://blog.csdn.net/bluishglc/article/details/12709557 Spring-Security的启动加载细节 Spring-Securit ...
- Spring源码-IOC部分-Xml Bean解析注册过程【3】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- Spring源码解析 – @Configuration配置类及注解Bean的解析
在分析Spring 容器创建过程时,我们知道容器默认会加载一些后置处理器PostPRocessor,以AnnotationConfigApplicationContext为例,在构造函数中初始化rea ...
- Spring源码解析之ConfigurationClassPostProcessor(二)
上一个章节,笔者向大家介绍了spring是如何来过滤配置类的,下面我们来看看在过滤出配置类后,spring是如何来解析配置类的.首先过滤出来的配置类会存放在configCandidates列表, 在代 ...
- Spring源码解析之ConfigurationClassPostProcessor(三)
在上一章笔者介绍了ConfigurationClassParser.doProcessConfigurationClass(...)方法,在这个方法里调用了processImports(...)方法处 ...
- Spring源码-IOC部分-自定义IOC容器及Bean解析注册【4】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- Spring读书笔记——bean解析
前情回顾 上篇<Spring读书笔记--bean加载>我们从代码角度介绍了有哪些类负责解析XML文件,又是如何一步步从XML格式脱变成我们熟悉的bean的,直到DefaultBeanDef ...
- spring源码阅读(1)bean解析
public class Test { public static void main(String[] args) throws Exception { BeanFactory beanFactor ...
- Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...
随机推荐
- mongo数据库的各种查询语句示例
左边是mongodb查询语句,右边是sql语句.对照着用,挺方便. db.users.find() select * from users db.users.find({"age" ...
- 第十九单元 nfs服务
===============服务端 介绍: NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布.功能是通过 ...
- LeetCode(78):子集
Medium! 题目描述: 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3] 输出: [ [3 ...
- 【linux】Linux误删C基本运行库libc.so.6急救方法
转自:http://www.cnblogs.com/fjping0606/p/4551475.html 下面全文都是拷贝的上面链接的内容. 首先普及一下关于libc.so.6的基本常识: libc.s ...
- Spring.Net 简单实例-02(属性注入)
说明:接续Spring.Net 简单实例-01(IOC) 话不多说看操作 1:为UserInfo添加属性 2: 修改App.config中代码 <?xml version="1.0&q ...
- SQL得到任意一个存储过程的参数列表sp_procedure_params_rowset
SQL得到任意一个存储过程的参数列表sp_procedure_params_rowsetexec sp_procedure_params_rowset 'up_rpt营业收入汇总表' PROCEDUR ...
- 迅速上手:使用taro构建微信小程序基础教程
前言 由于微信小程序在开发上不能安装npm依赖,和开发流程上也饱受诟病:Taro 是由京东·凹凸实验室(aotu.io)倾力打造的 多端开发解决方案,它的api基于react,在本篇文章中主要介绍了使 ...
- MyBatis-Plus工具快速入门
MyBatis-Plus官方文档:http://mp.baomidou.com/#/quick-starthttp://mp.baomidou.com/guide/#%E7%89%B9%E6%80%A ...
- [转] Webpack 打包优化之体积篇
谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...
- KnocoutJs+Mvc+BootStrap 学习笔记(Mvc)
Mvc 1.Html 增加扩展方法 using System.Web.Mvc; namespace KnockoutBootstrapMvc.Entensions { public static ...