Spring容器生命周期
执行ConfigurableApplicationContext.refresh()
方法是Spring容器生命周期开始的主要入口点. 而调用BeanDefinitionRegistryPostProcessor
和BeanFactoryPostProcessor
两个后置处理是最重要的一个步骤,因为会触发ConfigurationClassPostProcessor
执行postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
方法,实现classpath下指定包中的类文件扫描。
认识BeanDefinition
BeanDefinition
是一个接口,用于描述Bean的信息,例如有哪些属性,构造方法参数,bean的作用域,是否懒加载等。当调用applicationContext.getBean(…)
获取Bean实例对象时,如果Bean还没有创建,则会通过BeanDefinition
中的描述信息创建Bean,BeanDefinition有如下几个重要的实现类.
- 启动类使用了
AnnotatedGenericBeanDefinition
封装。 - classpath下执行包扫描被扫描到的类使用:
ScannedGenericBeanDefinition
,在ClassPathScanningCandidateComponentProvider
418行即可看到。 - 被导入的bean使用
AnnotatedGenericBeanDefinition
。
例如: 通过spring.factories
配置的类是被启动类导入的Bean, 非静态的内部配置类在org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader
137行断点即可看到 - 通过
@Bean
方法配置的bean使用ConfigurationClassBeanDefinition
当调用applicationContext.getBean()
获取Bean时,如果bean对象还未创建则,会调用AbstractBeanFactory.getMergedLocalBeanDefinition()
将不同类型的BeanDefinition
转成RootBeanDefinition
认识BeanFactoryPostProcessor
中文翻译为Bean工厂后置处理器,开发者可以通过实现该接口,在其接口方法postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
中通过beanFactory
修改已存在的BeanDefinition属性,也可以用于手动添加自定义的BeanDefinition
。
BeanDefinitionRegistryPostProcessor
是BeanFactoryPostProcessor
的子类,添加了postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
方法,两个接口方法作用基本相同。
但是子类中的postProcessBeanDefinitionRegistry(…)
方法在父类的postProcessBeanFactory(…)
方法之前执行.
2.1 调用prepareRefresh() 方法激活容器
调用该方法仅是为了将AbstractApplicationContext
中的AtomicBoolean active
成员变量值设置成true,表示Spring容器激活,可以调用applicationContext.getBean(…)
方法,在此之前调用都将抛出”has not been refreshed yet”异常.
2.2 设置ConfigurableListableBeanFactory对象所需要的必要组件
prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
这个方法主要用于向beanFactory中添加一些必要的初始化组件:
- 添加
SpringEL表达式解析器
- 添加
ApplicationContextAwareProcessor
后置处理器,当实例化Bean时用于检测其是否实现Aware方法
,实现注入。 - 添加
ApplicationListenerDetector
后置处理器,用于检测bean是否实现了ApplicationListener
,如果是则添加到AbstractApplicationContext
的监听器集合中。
2.3 调用BeanFactoryPostProcessor,实现包扫描
-
获取
AbstractApplicationContext
中成员变量beanFactoryPostProcessors
保存的BeanFactoryPostProcessor
, 遍历调用BeanDefinitionRegistryPostProcessor
接口实现类. 此时只有三个BeanFactoryPostProcessor
实现类,但是只有前两个是实现了BeanDefinitionRegistryPostProcessor
接口。
A. CachingMetadataReaderFactoryPostProcessor
注册SharedMetadataReaderFactoryBean
工厂bean,其实现了FactoryBean接口,主要用于在类路径下class文件扫描时读取类信息,相关类:SimpleMetadataReader
,ClassPathScanningCandidateComponentProvider
B. ConfigurationWarningsPostProcessor
用于对启动类上设置的扫描包进行验证,用户设置的扫描包不能是:org.springframework
和org
,否则抛出异常.C. PropertySourceOrderingPostProcessor
PropertySourceOrderingPostProcessor
仅实现了BeanFactoryPostProcessor
,目的将ConfigurableEnvironment
中的名称为”defaultProperties
”的PropertySource
放在集合最后 -
通过
beanFactory.getBeanNamesForType(…)
获取Spring容器中实现BeanDefinitionRegistryPostProcessor
接口的类名称集合并遍历,如果bean同时是PriorityOrdered
接口的实现类,则通过getBean()
获取实例对象,此时容器中只有一个ConfigurationClassPostProcessor
,主要用于类路径下文件扫描. -
调用
ConfigurationClassPostProcessor
实现的postProcessBeanDefinitionRegistry()
方法,开始执行类路径扫描。通过SimpleMetadataReader
指定包下的class文件,如果扫描到的类是一个配置类,或者是通过@Import
注解导入的类会采用递归的方式继续判断是否是配置类,直到是解析到普通的Bean,然后通过this.reader.loadBeanDefinitions(configClasses)
,过滤得到符合条件注解要求的BeanDefinition
-
因为执行完类路径扫描后,可能有实现
BeanDefinitionRegistryPostProcessor
和BeanFactoryPostProcessor
接口的Bean,所以需要再次通过beanFactory.getBeanNamesForType(…)
获取Spring中实现BeanDefinitionRegistryPostProcessor
接口的类名称集合,去除已经调用过的实现类ConfigurationClassPostProcessor
,遍历bean名称获取实现了Ordered
接口的实例,排序后回调接口方法 -
在while(reiterate) 中遍历调用没有实现排序接口
BeanDefinitionRegistryPostProcessor
的bean。为什么要用while语句? 为了防止在回调方法中注入一个新的
BeanDefinitionRegistryPostProcessor
实现类.这样可以调用新的BeanDefinitionRegistryPostProcessor
-
回调
BeanDefinitionRegistryPostProcessor
父类BeanFactoryPostProcessor
的方法postProcessBeanFactory(beanFactory)
无排序 -
获取
BeanFactoryPostProcessor
接口实现类,按照排序接口类型分类排序,回调接口方法- 遍历执行实现
org.springframework.core.PriorityOrdered
排序的BeanFactoryPostProcessor
- 遍历执行实现
org.springframework.core.Ordered
排序的BeanFactoryPostProcessor
- 遍历执行未实现排序接口的
BeanFactoryPostProcessor
- 遍历执行实现
2.4 注册BeanPostProcessors用于处理bean
-
通过
beanFactory.getBeanNamesForType(…)
获取BeanPostProcessor
类型的beanName集合 -
遍历beanNames,按照排序接口类型分类并排序,如果是
MergedBeanDefinitionPostProcessor
实现类,也将独立保存到一个集合中,这接口主要用于Spring内部使用.最后得到如下三个集合,通过abstractBeanFactory.addBeanPostProcessor(postProcessor)
保存BeanPostProcessor
-
添加
ApplicationListenerDetector
,用于收集事件监听器实现类,将其添加到AbstractApplicationContext的applicationListeners
集合中注意点: 注册
BeanPostProcessor
时,会调用getBean(beanName)
获取BeanPostProcessor实例对象
,而getBean()
方法内部又会调用已经存在的BeanPostProcessor
处理新创建的Bean,因此先注册的BeanPostProcessor
可能会处理后注册的BeanPostProcessor
,例如:
实现PriorityOrdered
接口的BeanPostProcessor
会处理后注册的实现Ordered
的BeanPostProcessor
实现Ordered
接口的BeanPostProcessor
会处理后注册的没有实现排序接口的BeanPostProcessor
2.5 注册事件广播器到Spring容器
initApplicationEventMulticaster()
方法通过beanFactory.registerSingleton()
向Spring容器注册事件广播器,用于广播事件
2.6 注册事件监听器
用于加载开发者通过注解配置的监听器,只能监听ContextRefreshedEvent
之后的事件
2.7 完成所有非懒加载Bean的实例化
finishBeanFactoryInitialization(beanFactory);
主要通过获取所有beanName,遍历通过AbstractBeanFactory.getBean(name)
方法完成bean的创建. 所有的bean完成实例化之后,重新遍历bean实例,查找实现SmartInitializingSingleton
接口的bean,回调接口方法。
2.8 发布ContextRefreshedEvent事件
ContextRefreshedEvent
事件在ApplicationStartedEvent
和ApplicationReadyEvent
事件之前发布。