Springboot扫描注解类的入口在AbstractApplicationContext的refresh中,对启动步骤不太了解的,可参考springboot启动过程源码_spring-boot-starter源码-优快云博客




BeanDefinitionRegistryPostProcessor接口有多个实现类,扫描Controller、Service等组件,这里使用的是ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry。


查看processConfigBeanDefinitions方法中的parser.parse(candidates),作用为解析所有@Configuration类,所有组件注解都包含@Configuration,实际就是解析
所有组件。

下图,如果BeanDefinition属于AnnotatedBeanDefinition,就开始解析注解bean定义。




在处理配置类的注解时,会找到ComponentScans注解,并解析其内容(@SpringBootApplication注解就包含@ComponentScan),由于未配置basePackages属性,解析到最后使用声明的类名。


后面扫描包,通过查看doScan方法的实现类,可以看到有两个,一个是ClassPathBeanDefinitionScanner(spring),另一个是ClassPathMapperScanner(使用mybatis集成的)。


这里使用的是ClassPathBeanDefinitionScanner的doscan方法。

扫描basePackage下的组件。


再对beanDefinition做一些后置处理。



上面完成了初步的BeanDefinition构建,在checkCandidate方法中将决定是否注册该BeanDefinition。



调用registerBeanDefinition方法开始注册BeanDefinition。


在DefaultListableBeanFactory的registerBeanDefinition方法中进行注册。

判断是否开始了bean创建。

已经有2个框架类开始创建,进入synchronized方法块进行添加。


注册完bean definition后同时给bean name注册别名。

关于BeanDefinition中的class是如何加装的,请查看ConfigurationClassPostProcessor类的processConfigBeanDefinitions方法。

ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForConfigurationClass

经过多个方法调用后,使用 ClassUtils.forName(className, classLoader)加载class

这里Class.forName的initialize设置为false,只是与class文件进行了关联,还未初始化,初始化在后面。
