Spring IOC容器生命周期阶段总结

Posted talk.push

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IOC容器生命周期阶段总结相关的知识,希望对你有一定的参考价值。

Spring IOC容器生命周期

BeanFactory和ApplicationContext有何区别?

到底什么才是Spring容器呢?我们需要分清楚以上两个类的区别。
● ApplicationContext是BeanFactory的子接口
● BeanFactory是一个底层的IOC容器,提供了IOC容器的基本实现,而ApplicationContext则是BeanFactory的超集提供了丰富的企业级特性。
● ApplicationContext是委托DefaultListableBeanFactory来实现Bean的依赖查找和依赖注入。

接下来就详细介绍一下Spring容器的完整生命周期都做了哪些事情。
首先,入口是AbstractApplicationContext.refresh()方法其实是启动容器。这是一个抽象类,许多的应用上下文都实现了这个类。比如最常见的:

org.springframework.context.support.ClassPathXmlApplicationContext

接下来看下源代码中是长什么样子。

源码展示

@Override
	public void refresh() throws BeansException, IllegalStateException 
		synchronized (this.startupShutdownMonitor) 
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try 
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			

			catch (BeansException ex) 
				if (logger.isWarnEnabled()) 
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			

			finally 
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			
		
	

其中的阶段做的事情非常之多,阅读时难免会陷入某一个阶段中去,而无法做到对全局做一个把握,这里就是分解一下各个阶段所做的事情,从而对有一个全局的视角。Spring的体系比较庞杂,我们只能各个击破。

1. Spring应用上下文启动准备阶段

AbstractApplicationContext#prepareRefresh();

该方法为容器启动做准备

a. 启动时间
b. 容器状态标识
c. 初始化PropertySources-->initPropertySources()空方法留给子类实现
d. 检验Environment中的必须属性
e. 初始化事件监听集合
f. 初始化早期Spring事件集合

2. BeanFactory创建阶段

AbstractApplicationContext#obtainFreshBeanFactory();

通过模板方法模式在子类中实现容器的获取结果是DefaultListableBeanFactory。

Tips: 大多数应用上下文的实现都继承了AbstractRefreshableApplicationContext。

a. 刷新Spring应用上下文底层

BeanFactoryAbstractRefreshableApplicationContext#refreshBeanFactory()
	i. 销毁或关闭BeanFactory,如果已经存在的话。
	ii. 创建BeanFactory:createBeanFactory()
	iii. 设置BeanFactory Id
	iv. 设置“是否允许BeanDefinition重复定义”
	v. 设置“是否允许循环依赖”
	vi. 加载BeanDefinition:loadBeanDefinitions(DefaultListableBeanFactory)
	vii. 关联新建BeanFactory到Spring应用上下文

b. 返回Spring应用上下文底层BeanFactory=>getBeanFactory()

3. BeanFactory初始化阶段

AbstractApplicationContext#prepareBeanFactory()
a. 关联classloader
b. 设置Bean表达式处理器(SpringEL相关的内容)
c. 添加PropertyEditorRegistrar实现:ResourceEditorRegistrar
d. 添加Aware回调接口BeanPostProcessor实现:ApplicationContextAwareProcessor
e. 添加Aware回调接口作为依赖注入接口
f. 注册ResolvableDependency内建的非Bean对象:BeanFactory、ResourceLoader、ApplicationEventPublisher以及ApplicationContext
g. 注册ApplicationListenerDetector对象
	i. 对于符合ApplicationListener接口且是单例的Bean记录到singletonsName。后面会作为ApplicationListener关联到ApplicationContext中。
h. 注册LoadTimeWeaverAwareProcessor对象(AOP相关)
i. 注册单例对象:Environment、Java System Properties以及OS环境变量

4. BeanFactory后置处理阶段

针对容器的扩展

a. postProcessBeanFactory(beanFactory)
	i. 是个空方法,需要子类去扩展这个方法
b. InvokeBeanFactoryPostProcessors(beanFactory)
	i. 迭代所有BeanFactoryPostProcessor判断它是否是BeanDefinitionRegistryPostProcessor类型
		1. 如果是则执行其postProcessBeanDefinitionRegistry方法,并在registryProcessors集合中加入当前迭代对象BeanFactoryPostProcessor。
		2. 否则直接加入regularPostProcessors集合中,表示是常规的PostProcessor。
	ii. Spring容器中的BeanFactoryPostProcessor有可能实现了PriorityOrdered、Ordered接口,也可能没有实现。对他们进行分别归类之后按照PriorityOrdered、Ordered、常规的BeanFactoryPostProcessor的集合顺序去执行。
	iii. 分别遍历处理registryProcessors和regularpostProcessors两个集合对象,执行迭代对象的postProcessBeanFactory方法,因为其实集合的对象都实现了BeanFactoryPostProcessor接口。

5. BeanFactory注册BeanPostProcessor阶段

AbstractApplicationContext#registerBeanPostProcessors(beanFactory)// 针对Bean的扩展
	i. 注册PriorityOrdered类型的BeanPostProcessor Beans
	ii. 注册Ordered类型的BeanPostProcessor Beans
	iii. 注册普通的BeanPostProcessor Beans
	iv. 注册MergedBeanDefinitionPostProcessor Beans
	v. 注册ApplicationListenerDetector对象

6. 初始化国际化

initMessageSource()

● 在Spring容器中依赖查找MessageSource并根据情况设置其层次性
● 如果IOC容器中没有则创建一个DelegatingMessageSource并设置其层次性,然后在Spring容器中注册MessageSource单例对象

7. 初始化应用事件广播器

AbstractApplicationContext#initApplicationEventMulticaster()
a. 在Spring容器中判断并依赖查找ApplicationEventMulticaster对象,并赋值给当前容器的applicationEventMulticaster
b. 如果IOC容器中没有则创建一个SimpleApplicationEventMulticaster,然后在Spring容器中注册ApplicationEventMulticaster单例对象。

8. Spring应用上下文刷新阶段

初始化特殊Bean->onRefresh()

这个方法是一个空实现,提供给子类扩展。比如StaticWebApplicationContext、AbstractRefreshableWebApplicationContext子类则是提供了关于theme主题的实现。

this.themeSource = UiApplicationContextUtils.initThemeSource(this);

9. Spring注册监听器阶段

AbstractApplicationContext#registerListeners()
a. 添加当前应用上下文所关联的ApplicationListener集合对象
b. 添加BeanFactory所注册ApplicationListener Beans
c. 广播早期Spring事件

10. BeanFactory初始化完成阶段

AbstractApplicationContext#finishBeanFactoryInitialization(beanFactory)
a. BeanFactory关联ConversionService Bean(如果存在的话)
b. 添加StringValueResolver对象提供处理占位符操作
c. 依赖查找LoadTimeWeaverAware Bean
d. BeanFactory临时ClassLoader置为null
e. BeanFactory冻结配置
f. BeanFactory初始化非延迟单例Beans:beanFactory#preInstantiateSingletons()

11. Spring应用上下文启动完成阶段

AbstractApplicationContext#finishRefresh()
a. 清除ResourceLoader缓存:clearResourceCaches()
b. 初始化LifecycleProcessor对象:initLifecycleProcessor()
c. 调用LifecycleProcessor#onReFresh())方法
d. 发布Spring应用上下文已刷新事件:ContextRefreshedEvent
e. 向MBeanServer托管LiveBeans(可以通过jconsole查看)

12. Spring应用上下文启动阶段

AbstractApplicationContext#start()
a. 这个方法一般起辅助作用,可以不调用它。。
b. 作用一:启动LifecycleProcessor
c. 作用二:发布Spring应用上下文已启动事件:ContextStartedEvent事件

13. Spring应用上下文停止阶段:

AbstractApplicationContext#stop()
a. 跟start方法一样是辅助作用。
b. 作用一:停止LifecycleProcessor
c. 作用二:发布Spring应用上下文已停止事件:ContextStoppedEvent事件

14. Spring应用上下文关闭阶段:

AbstractApplicationContext#close()
a. Spring容器设置状态标识:active=false,closed=true
b. Live Beans JMX撤销托管
c. 发布Spring应用上下文的已关闭事件
d. 关闭LifecycleProcessor
e. 销毁Spring Beans
f. 关闭BeanFactory
g. 回调onClose()
h. 如果ShutdownHook这个线程不为null,remove ShutDown Hook Thread

其中start和stop方法用的很少,它们只是起到一个辅助IOC容器的作用,对了解IOC容器的整个生命周期不是非常重要,重点关注refresh方法即可。

以上是关于Spring IOC容器生命周期阶段总结的主要内容,如果未能解决你的问题,请参考以下文章

spring学习总结007 --- IOC容器级生命周期接口

Spring框架介绍及使用

spring IOC 容器中 Bean 的生命周期

Spring4学习回顾之路06- IOC容器中Bean的生命周期方法

Spring bean 的生命周期注入方式和作用域

Spring Bean的生命周期