springboot是以spring为基础的,所以本文的大部分内容还是在分析spring,只不过是在spring boot的场景下分析。关于spring boot的自动化装配我们会在下一篇文章分析。本文分为三个部分,通过阅读spring boot源码和参阅了大量其他的文章,耗时两个礼拜,才总结出来。因为spring的源码篇幅巨大、设计思想很多,基本是java程序员必须掌握的技能,所以无论花费多大的时间精力去分析都是值得的。
- 第一部分:基本概念:一些通用的东西
- 第二部分:bean生命周期
- 第三部分:源码分析
本文源码分析基于springboot版本为2.1.3,对应的spring版本为5.1.5
了解一二两个部分对spring的整个源码分析会有很大的帮助。至于源码分析部门还是建议大家自已去debug一遍。因为我的源码分析部分没有办法做到非常详尽。
Part 1 基本概念
1.1 必须知道的接口、类
1.1.1 Aware
- 源码注释
A marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method.
- 翻译
一个超级接口,指示一个bean可以被spring 容器通过回调的方式通知。
比如要在Bean中获取它自已的BeanFactory, 那自定义的Bean实现BeanFactoryAware接口就可以了,BeanFactoryAware.setBeanFactory会在bean初始化之前被容器调用
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
- 大白话
使Bean可以具备获取容器资源的能力
1.1.2 BeanFactoryPostProcessor
- 接口声明
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
- 源码注释
Allows for custom modification of an application context's bean definitions, adapting the bean property values of the context's underlying bean factory.
- 翻译
BeanFactory的后置处理器。可以在Bean创建之前,BeanDefinition创建之后,去修改BeanDefinition(甚至可以修改Bean的属性值)。但是不建议直接修改bean的值,修改BeanDefinition的属性是可以的。为什么不建议在这里修改Bean的一些属性?如果要修改那么肯定需要获取bean,一旦执行获取操作,不存在就会创建bean。但是在这个阶段很多bean的PostProcessor还没有注册。那么(1)会导致bean的一些后置处理器不会执行(比如你自已定义的)(2)会导致bean的一些属性没有自动注入,因为自动注入(@autowire)也是通过bean的PostProcessor完成的。所以除非你确定你在做什么,所以不要在这里去执行获取bean操作。 - 大白话
任何Bean实现BeanFactoryPostProcessor接口,会被容器扫描到,postProcessBeanFactory会被调用。
1.1.3 BeanPostProcessor
- 接口声明
public interface BeanPostProcessor {
// Bean 初始化回调之前被调用
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// Bean 初始化回调后被调用
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
何为Bean的初始化回调?InitializingBean的afterPropertiesSet 和自定义的init-method
- 源码注释
Factory hook that allows for custom modification of new bean instances
- 翻译
Bean的后置处理器。可以修改bean实例。再强调一句,不要在BeanFactoryPostProcessor的实现里去获取bean和修改bean
1.1.4 BeanDefinition
- 解释
BeanDefinition是bean在spring中的描述(比如bean的有那些属性,值是什么,有那些注解等元信息),有了BeanDefinition我们就可以创建Bean。注意BeanDefinition和Bean区别。特别是在我们和别人讨论或者看别人的分析的时候,要清楚我们在讨论的是BeanDefinition还是bean。BeanDefinition就相当于我们定义的类,bean就相当于我们实例的对象。 -
BeanDefinition具体的实现类如下
- BeanDefinition各个实现的具体应用场景
BeanDefinition有很多的子实现,不同的子实现应用不同的场景。网上有很多的总结,但是我不知道是不是因为版本的问题,我debug出来的结果和他们的有些不同。比如说AnnotatedGenericBeanDefinition表示@Configuration注解注释的类,但是我debug出来的结果是只要是通过.class文件扫描出来的bean,哪怕是@Configuration注解的也是用的ScannedGenericBeanDefinition。所以大家注意区分,重点关注源码上面的注释部分(尽管很多注释的地方,读了也不知道说的什么,但有比没有好)
- RootBeanDefinition
直接解读官方的注释
// 在运行时root bean表示一个merge bean(存在父子关系,所以需要合并,关于MergedBeanDefinition下面有解释)
* A root bean definition represents the merged bean definition that backs
* a specific bean in a Spring BeanFactory at runtime.
//可以用来创建具有继承关系的bean
* It might have been created
* from multiple original bean definitions that inherit from each other,
* typically registered as {@link GenericBeanDefinition GenericBeanDefinitions}.
// RootBeanDefinition在运行时是bean的一个统一的定义,那么本身不是用RootBeanDefinition 定义,也会创建一个新的RootBeanDefinition。AbstractBeanFactory 中就专门创建了一个对象mergedBeanDefinitions用来存放,并且和DefaultListableBeanFactory中beanDefinitionMap的大小相等。
* A root bean definition is essentially the 'unified' bean definition view at runtime.
*
// RootBeanDefinition可以用来创建自定义的BeanDefinition
* Root bean definitions may also be used for registering individual bean definitions
* in the configuration phase. However,
// 从Spring 2.5开始推荐使用GenericBeanDefinition,为什么我们下面讲
* since Spring 2.5, the preferred way to register
* bean definitions programmatically is the {@link GenericBeanDefinition} class.
// GenericBeanDefinition 允许动态的定义父BeanDefinition(这里的动态不知道什么意思,在源码中没有发现在上面地方使用这个动态),不像RootBeanDefinition是硬编码的
* GenericBeanDefinition has the advantage that it allows to dynamically define
* parent dependencies, not 'hard-coding' the role as a root bean definition.
*
- ChildBeanDefinition
可以从父BeanDefinition继续属性,通过构造函数或者setParentName可以设置父BeanDefinition - GenericBeanDefinition
GenericBeanDefinition是官方推荐的BeanDefinition,因为GenericBeanDefinition一个类就可以替代RootBeanDefinition和ChildBeanDefinition的。主要是因为GenericBeanDefinition可以直接设置父BeanDefinition。个人感觉也没啥。我们看下源码中注解
/**
// 一站式商店,可以构造参数、属性值(MutablePropertyValues)
* GenericBeanDefinition is a one-stop shop for standard bean definition purposes.
* Like any bean definition, it allows for specifying a class plus optionally
* constructor argument values and property values. Additionally, deriving from a
* parent bean definition can be flexibly configured through the "parentName" property.
*
// 用GenericBeanDefinition注册用户可见的bean definitions。用户可见的意思就是可以在后置处理器中获取
* In general, use this {@code GenericBeanDefinition} class for the purpose of
* registering user-visible bean definitions (which a post-processor might operate on,
* potentially even reconfiguring the parent name). Use {@code RootBeanDefinition} /
* {@code ChildBeanDefinition} where parent/child relationships happen to be pre-determined.
*
总的来说,就是推荐使用GenericBeanDefinition
- ConfigurationClassBeanDefinition
/**特指从configuration class中创建的bean definition
* {@link RootBeanDefinition} marker subclass used to signify that a bean definition
* was created from a configuration class as opposed to any other configuration source.
* Used in bean overriding cases where it's necessary to determine whether the bean
* definition was created externally.
*/
一般就是指用@Bean注解的bean
- AnnotatedGenericBeanDefinition
springboot的启动类的bean表述是用该类定义的。类中有一个重要的属性AnnotationMetadata可以用来获取bean的所有的注解信息 - ScannedGenericBeanDefinition
springboot是从启动来开始来扫描bean且是通过扫描.class文件的方式扫描的,所以除了启动类意外,所有的有@Component(包括@Configuaration, @service, @Controller)注解的bean都是包装成ScannedGenericBeanDefinition的, 但是@Bean注解的bean不是 - MergedBeanDefinition
其实spring中并没有该类的具体定义,但是源码中又存在像getMergedBeanDefinition方法和MergedBeanDefinitionPostProcessor这个bean级别的后置处理器。其实在spring中MergedBeanDefinition对应的具体类是RootBeanDefinition。那么什么是MergedBeanDefinition?MergedBeanDefinition又是在springboot源码中什么时候处理的
- 什么是MergedBeanDefinition
MergedBeanDefinition表示将存在父子关系的bean的合并,也就是说你可以定义个一对存在继承关系的bean。spring会在某个时候将其合并(将父bean的属性拷贝一份到子bean) - MergedBeanDefinition的merge发生在那里
在执行BeanDefinitionRegistryPostProcessor(发现bean,注册BeanDefinition)之前。springboot是通过如下代码去容器中查找BeanDefinitionRegistryPostProcessor后置处理器的
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)
合并BeanDefinition就是在DefaultListableBeanFactory.getBeanNamesForType方法中
1.1.5 ConfigurationClassPostProcessor
用于处理启动配置类,@SpringBootApplication中存在@Configuration注解
{@link BeanFactoryPostProcessor} used for bootstrapping processing of
{@link Configuration @Configuration} classes.
首先这是一个实现了BeanFactoryPostProcessor的后置处理器,而且还是实现了BeanDefinitionRegistryPostProcessor的后置处理器。spring的bean扫描、注册、自动配置等一切功能都由ConfigurationClassPostProcessor开始
1.2 Full 模式和Lite模式
此部分参考了 Spring的@Configuration配置类-Full和Lite模式,并结合了自已的源码分析
Full 模式和Lite模式是针对spring中的bean而言的,在ConfigurationClassUtils.checkConfigurationClassCandidate方法中有关于是Full 还Lite模式的判断
if (isFullConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (isLiteConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
1.2.1 Full模式和Lite模式的定义
官方定义为:
类上有@Configuration注解的就是Full模式。
类上没有@Configuration注解,但是里面有@Bean方法就称为Lite模式。
透过源码再看这个定义是不完全正确的,而应该是有如下case均认为是Lite模式的配置类:
- 类上标注有@Component注解(包含@Service、@Controller)
- 类上标注有@ComponentScan注解
- 类上标注有@Import注解
- 类上标注有@ImportResource注解
- 若类上没有任何注解,但类内存在@Bean方法
以上case的前提均是类上没有被标注@Configuration,在Spring 5.2之后新增了一种case也算作Lite模式:标注有@Configuration(proxyBeanMethods = false),注意:此值默认是true哦,需要显示改为false才算是Lite模式
细心的你会发现,自Spring5.2(对应Spring Boot 2.2.0)开始,内置的几乎所有的@Configuration配置类都被修改为了@Configuration(proxyBeanMethods = false),目的何为?答:以此来降低启动时间,为Cloud Native继续做准备。
1.2.2 Full模式和Lite模式的不同
Full模式下:配置类会被CGLIB增强(生成代理对象),放进IoC容器内的是代理
Lite模式下:放进IoC容器内的是类的实例,没有代理
代理的好处就是我们可以在方法的前后做一些其他的事情(AOP思想)
1.2.3 为什么需要Full模式和Lite模式
假设已经存在Persion类,请思考下面两段代码中的persion1和persion2是不是相等的(是不是同一个对象)
@Configuration
public class MainConfiguration{
@Bean("persion1")
public Persion persion1() {
return new Persion("payne");
}
@Bean("persion2")
public Persion persion2() {
return persion1();
}
}
@Component
public class MainConfiguration{
@Bean("persion1")
public Persion persion1() {
return new Persion("payne");
}
@Bean("persion2")
public Persion persion2() {
return persion1();
}
}
在Full模型下,也就是代码片段一。persion1和persion2是相等的,尽管在persion2()方法中调用了persion1()方法。persion1()中每次是new 一个Persion的
在Lite模式下,也就是代码片段二,persion1和persion2是不相等的。
如果没有代理对象,我们是做不到代码一中的效果的。
Part 2 Bean生命周期
spring bean 的生命周期在BeanFactory接口注释中有完整的描述。分为两个部分,第一部分是bean可使用之前的部分,第二部分为shutdown bean factory之后的
// 第一部分
* Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:
*
* - BeanNameAware's {@code setBeanName}
*
- BeanClassLoaderAware's {@code setBeanClassLoader}
*
- BeanFactoryAware's {@code setBeanFactory}
*
- EnvironmentAware's {@code setEnvironment}
*
- EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
*
- ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)
*
- ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)
*
- MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)
*
- ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)
*
- ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)
*
- {@code postProcessBeforeInitialization} methods of BeanPostProcessors
*
- InitializingBean's {@code afterPropertiesSet}
*
- a custom init-method definition
*
- {@code postProcessAfterInitialization} methods of BeanPostProcessors
*
*
//第二部分
* On shutdown of a bean factory, the following lifecycle methods apply:
*
* - {@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
*
- DisposableBean's {@code destroy}
*
- a custom destroy-method definition
*
整理如下:
第一部分
- BeanNameAware.setBeanName
- BeanClassLoaderAware.setBeanClassLoader
- BeanFactoryAware.setBeanFactory
- EnvironmentAware.setEnvironment
- EmbeddedValueResolverAware.setEmbeddedValueResolver
- ResourceLoaderAware.setResourceLoader
- ApplicationEventPublisherAware.setApplicationEventPublisher
- MessageSourceAware.setMessageSource
- ApplicationContextAware.setApplicationContext
- ServletContextAware.setServletContext
- BeanPostProcessors.postProcessBeforeInitialization
- InitializingBean.afterPropertiesSet
- a custom init-method definition
- BeanPostProcessors.postProcessAfterInitialization
以上生命周期是按发生的顺序排序的,最早的生命周期BeanNameAware.setBeanName也是发生在bean实例化、填充属性之后的,此时的bean已经是一个完整的对象了,已经是可用状态。
借用参考文献一的图如下:
第二部分
- DestructionAwareBeanPostProcessors.postProcessBeforeDestruction
- DisposableBean.destroy
- a custom destroy-method definition
bean更完整的生命周期
但是以上的上面周期仅仅是我们自已定义的bean能看到的生命周期,那spring 本身一些bean的生命周期是没有包含在这里面的。很久之前写过一篇通过xml注册bean的生命周期文章中总结过一个完整的图,在这里同样适用,因为spring的bean生命周期是一样的。大家也可以再看一下这篇文章前面总结的一些概念spring bean 生命周期。我们再把图搬过来一下
这个图第一行BeanDefinitionRegistryPostProcessor的实例化就是指的我们在1.1.5节提到的ConfigurationClassPostProcessor。重要的事情多提几遍ConfigurationClassPostProcessor是spring boot中IOC的起点。
Part 3 源码分析
源码分析部分,我会在我认为重要的地方写上注释,也会去掉一些我任认为不重要的地方。
目录的编号对应注释前面的编号
springboot的代码篇幅比较大。我们暂且分为三个大的部分
-
- 启动初始化部分
-
- bean扫描部分
-
- bean的实例化部分
启动初始化部分
3.1、SpringApplication.run方法
public ConfigurableApplicationContext run(String... args) {
ConfigurableApplicationContext context = null;
Collection exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//(1)添加一些基本的类型转换器(2)配置环境(1、配置文件,2、激活了那个profile(3)占位符等(@value注解的占位符))
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
//打印springboot的banner
Banner printedBanner = printBanner(environment);
//创建ApplicationContent, (1)DefaultListableBeanFactory也在这里创建 (2) 这里有一个非常重要的BeanFactoryPostProcessor:ConfigurationClassPostProcessor在这里面注册
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//(3)加载primarySources(其实就是我们的启动类),将其注册为一个bean(bean的注册指创建一个BeanDefinition,然后放到beanDefinitionMap对象中,并没有完成实例化)
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//(4) 最复杂,关键的地方,下面详细讲解
refreshContext(context);
// (5)当ApplicationContent refresh 后,执行该方法,这里是一个空的实现
afterRefresh(context, applicationArguments);
stopWatch.stop();
listeners.started(context);
callRunners(context, applicationArguments);
listeners.running(context);
return context;
}
3.1.4 springApplication.refreshContext详解
springApplication.refreshContext方法实际调用的是AbstractApplicationContext.refresh()方法。下面直接看该方法
public void refresh() throws BeansException, IllegalStateException {
// (1)无重要内容,主要设置启动时间,激活标志
prepareRefresh();
// (2)无重要内容,获取bean factory(实际类型为DefaultListableBeanFactory在上面已经创建过了)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// (3)添加了两个重要的BeanPostProcessor,(1)ApplicationContextAwareProcessor,bean生命周期关于Aware部分的就是通过添加该bean post processor 实现 (2)ApplicationListenerDetector,关于事件监听(发布-订阅者模式)是通过该bean post processor 实现的(3)添加了3个bean(environment, systemProperties,systemEnvironment)看名字就知道是关于系统一些变量的
prepareBeanFactory(beanFactory);
// (4)无具体实现,其他content可以重写改方法
postProcessBeanFactory(beanFactory);
// (5)调用一些已经注册为bean的BeanFactoryPostProcessor,还记的创建content时候我们提到的那个 重要的ConfigurationClassPostProcessor类吗?
invokeBeanFactoryPostProcessors(beanFactory);
// (6)Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
//(7)国际化相关处理
initMessageSource();
//(8) 事件通知机制,发布订阅者实现
initApplicationEventMulticaster();
// (9)其他的上下文比如web应用等可以实现改方法,用来实例化一些特殊的bean
onRefresh();
// (10)事件通知机制,注册事件
registerListeners();
// (11)我们在invokeBeanFactoryPostProcessors中扫描到了很对的bean,我们执行将其BeanDefinition注册到容器中,但是还没有实例化,那么实例化就在finishBeanFactoryInitialization中实例化。包括BeanPostProcessor的执行
finishBeanFactoryInitialization(beanFactory);
// (12)Last step: publish corresponding event.
finishRefresh();
}
3.2 bean的扫描部分
3.2.1 invokeBeanFactoryPostProcessors
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* Must be called before singleton instantiation.
*/
该方法的注释写的很明白,实例化并且调用注册为bean的BeanFactoryPostProcessor,这里面会调用我们在createApplicationContext方法中注册为bean的ConfigurationClassPostProcessor对象,该对象是是一个BeanFactoryPostProcessor。试想一下spring boot是如何找到我们定义的bean的呢?其他就是通过ConfigurationClassPostProcessor
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
// 后置处理器已经执行过的bean,防止执行多次
Set processedBeans = new HashSet<>();
// 将后置处理器分类,具体的见代码下面的解释
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List regularPostProcessors = new ArrayList<>();
List registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//(1) 执行invokeBeanDefinitionRegistryPostProcessors registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// 见下面解释
List currentRegistryProcessors = new ArrayList<>();
// 获取BeanDefinitionRegistryPostProcessor的bean名称,实际上注册为bean且类型是BeanDefinitionRegistryPostProcessor的类就是ConfigurationClassPostProcessor,且只有这一个
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// ConfigurationClassPostProcessor是实现了PriorityOrdered接口的
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//beanFactory.getBean 当bean没有实例化的时候,会实例化,所以ConfigurationClassPostProcessor之前只是一个BeanDefinition,在这里会实例化
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// (1)这里才是正式的ConfigurationClassPostProcessor, 会将所有满足bean条件的BeanDefinition注册 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 获取BeanDefinitionRegistryPostProcessors 类型的bean 并且实现 Ordered接口
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// (1)再次执行BeanFactoryPostProcessors, 注意如果上面已经执行过了,则不再执行 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 在执行上面后置处理器的过程中,会扫描到一些新的后置处理器,那么也要执行
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//(1) 执行invokeBeanDefinitionRegistryPostProcessors invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// (2)之前注册过一个重要的BeanFactoryPostProcessor: ConfigurationClassPostProcessor在这里会被调用,如果Bean是Full 模式的,那么cglib生成代理类放到beanDefinitionMap中
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 在扫描的过程中会发现新的实现BeanFactoryPostProcessor的bean,不如我们自已实现的一些后置处理器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 实现 PriorityOrdered的后置处理器先执行
// 实现Ordered的后置处理其次, 最后是其他的后置处理器
List priorityOrderedPostProcessors = new ArrayList<>();
List orderedPostProcessorNames = new ArrayList<>();
List nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//(2)执行invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
//(2)执行invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
//(2)执行invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
总结
(1)方法中有三个主要的对象:
- regularPostProcessors:普通的后置处理器,只实现BeanFactoryPostProcessor接口
- registryProcessors:除了实现BeanFactoryPostProcessor还实现BeanDefinitionRegistryPostProcessor的后置处理器
- currentRegistryProcessors:在容器中注册为bean且类型是BeanDefinitionRegistryPostProcessor的后置处理器(注意并发所有的后置处理器都会注册为bean),这里只有ConfigurationClassPostProcessor是满足条件的
上面对象中的后置处理器都执行完了,才会执行我们自已定义的后置处理器和我们再扫描过程中发现的后置处理器,我们经常使用@value("${变量名称}")来填充属性值就是通过在这里扫描到的PropertySourcesPlaceholderConfigurer这个后置处理器实现的
(2)执行顺序
- currentRegistryProcessors中实现PriorityOrdered的后置处理器最先执行
- currentRegistryProcessors中实现Ordered的后置处理器其次
- registryProcessors中的后置处理器
- regularPostProcessors中的后置处理器最后
- 我们自已在代码注册的后置处理器(就是通过ConfigurationClassPostProcessor才让容器发现我们自已定义的后置处理器的,所以肯定是最后执行)
两条原则
1. 先执行实现BeanDefinitionRegistryPostProcessor的后置处理器,后执行实现BeanFactoryPostProcessor的限制性(注意执行的方法不一样)
2. 实现PriorityOrdered的后置处理器先执行,实现Ordered的后执行
结合代码来说就是BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry先执行,BeanFactoryPostProcessor.postProcessBeanFactory后执行。BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor实现类,所以ConfigurationClassPostProcessor先执行postProcessBeanDefinitionRegistry来注册BeanDefinition,然后执行postProcessBeanFactory将Full模式的bean class用cglib生成代理类放到beanDefinitionMap中
3.2.1.1 invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
// 调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
postProcessBeanDefinitionRegistry实际处理逻辑在processConfigBeanDefinitions中
ConfigurationClassPostProcessor.processConfigBeanDefinitions处理逻辑
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List configCandidates = new ArrayList<>();
// 获取当前content所有的BeanDefinition(没有实例化的bean)
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//(1)关于Full模式和life模式参见文章末尾,这里主要是找出声明了注解@Configuration或者@Component的类(注意像@Service,@Controller等存在嵌套的元注解@Component也是满足这里的条件的)
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// (2) 判断该类有没有可能是configuration 类
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 由于springboot的启动类上是有@SpringBootApplication注解的,该注解是存在@Configuration嵌套注解的,所以启动类肯定是满足这个条件的configCandidates里面最起码是存在启动类的这个对象的
if (configCandidates.isEmpty()) {
return;
}
// 创建一个@Configuration class解析类
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set candidates = new LinkedHashSet<>(configCandidates);
Set alreadyParsed = new HashSet<>(configCandidates.size());
//(4)注意这里是一个循环,正常情况下,这里的candidates里面只有一个springboot启动类,所以该循环的作用就是如果在扫描启动类的过程又碰到新的@Configuration class那么一直扫描下去,知道找出所有的@Configuration class,扫描完了其实Bean也就扫描完了
do {
parser.parse(candidates);
parser.validate();
Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//(5)Configuration class 中的@Bean 方法还没有注册BeanDefinition, 下面会注册(扫描@Import注解时,也会出现新的Configuration class(自动配置))
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 在扫描到的Configuration class中也是有@Component注解的,那么循环的扫描
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
parse的调用链比较长,跳过无关的方法,扫描的核心逻辑在下面的方法中
3.2.1.1.4 ConfigurationClassParser.doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//如果该ConfigurationClass存在成员内部类,那么递归的扫描该类
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
// 处理@PropertySource注解
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理@ComponentScan 注解,ComponentScan会扫描我们启动类所在包下面所有的class文件,将所有有@Component注解的class会封装成BeanDefinition注册到容器中
Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 递归的扫描上面扫描到的scannedBeanDefinitions,如果该class上还有@PropertySource,@ComponentScan等注解就一直递归的处理
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// 处理@Import 注解, @SpringBootApplication的复合注解@EnableAutoConfiguration中存在@Import(AutoConfigurationImportSelector.class),springboot中的自动配置就是在这里通过这个注解实现的
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 处理 @ImportResource 注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 处理 @Bean注解的 方法
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 处理接口的默认方法
processInterfaces(configClass, sourceClass);
// 处理父类 superclass
if (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 recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
总结一下,方法的参数ConfigurationClass就是我们的启动的封装类,所以扫描就是从我们的启动类开始扫描的
(1) 方法作用
递归的扫描满足条件的Bean将其封装成BeanDefinition注册到容器上下文中。递归是从ConfigurationClass开始的,那么ConfigurationClass是如何定义的呢?通过如下方法判断。
ConfigurationClassUtils.checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory)
总结一下就是:如果类上面有@Component注解就是ConfigurationClassCandidate,因为@Configuration,@Service,@Controller等注解的元注解也是包含@Component的所以有这些注解的类也是ConfigurationClassCandidate。特别,如果类上没有注解但是,存在@Bean方法注解,那么该类也是ConfigurationClassCandidate
(2)扫描循序
扫描过程中只要碰到ConfigurationClassCandidate就递归扫描,碰到bean就将其BeanDefinition注册到容器中
- 成员内部类
- @PropertySource注解
- @ComponentScan注解
- @Import注解
- @ImportResource注解
- 内部@Bean方法
- 接口默认方法
- 父类
3.3 bean的注册部分
bean的注册主要实现在refresh方法的finishBeanFactoryInitialization
finishBeanFactoryInitialization详解
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 设置冻结BeanDefinition的flag,不希望在注册实例的时候改变bean的定义了
beanFactory.freezeConfiguration();
// (1)实例化剩下的非lazy的bean,有些bean比如自已定义的BeanPostProcessor还有容器的一些bean在之前已经实例化过了,所以这里实现剩下的,我们自已代码中很多就是这里实例化
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
3.3.1 preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {
// beanDefinitionNames 存放所有的之前扫描到的BeanDefinition
List beanNames = new ArrayList<>(this.beanDefinitionNames);
// 遍历所有的BeanDefinition,创建bean
for (String beanName : beanNames) {
// MergedBeanDefinition 之前已经详细说过概念,合并具有继承关系的BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 工程bean的处理
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean> factory = (FactoryBean>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction)
((SmartFactoryBean>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// (1)获取bean,获取不到则创建
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
3.3.1.1 doCreateBean
跳过不重要的调用关系直接看doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充bean属性,@autowire字段的属性就是在这里填充的,通过AutowiredAnnotationBeanPostProcessor这个后置处理器
populateBean(beanName, mbd, instanceWrapper);
// (1)初始化回调
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
3.3.1.1.1 initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// bean生命周期与Aware相关的在这里调用
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化回调前置操作
wrappedBean =
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 初始化回调
invokeInitMethods(beanName, wrappedBean, mbd);
// 初始化回调后置操作
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean =
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
参考文献
- Spring – Bean Life Cycle
- Spring源码分析之BeanFactoryPostProcessor调用过程详解
- Spring的@Configuration配置类-Full和Lite模式
- 深入理解SpringBoot的过滤条件--AutoConfigure
- EnableAutoConfiguration注解的工作原理