《Spring设计思想》32-spring context的生命周期

之前的章节讲完了Spring bean的生命周期,实例化-初始化-卸载-回收

这一节总结一下spring context的生命周期。

要归纳spring context的生命周期,先要弄明白Spring context是什么。spring context就是Spring framework启动之后的上下文,

上下文主要包括以下几个部分:

1.Environment 

2.ResourceLoader

3.ClassLoader

4:MessageSource

5.BeanFactory

6.BeanFactoryPostProcessor

7.BeanPostProcessor

8.Spring Beans

9:ConversionService

10.ApplicationEventListener

11.ApplicationEventPublisher/ApplicationEventMulticaster

还有一些特殊的工具类。以上的这些组建构成了spring运行时需要的大部分功能。我们在之前的章节里面也做了全面的介绍。那么spring的上下文怎么做到上面组建的组合呢,还是要在代码里面找答案:

在所有的spring context的父类 

AbstractApplicationContext中给了我们较为直观的感受:

AbstractApplicationContext中的属性有我们比较熟悉的:

1:environment,2:beanFactory,3:beanFactoryPostProcessors,4:applicationListeners,这些是我们spring context可以直接关联的组建,那么其余的组建在哪里呢,其实其余的组建都间接的存储在beanFactory中了。比如会把Environment/beanPostProcessor/BeanClassLoader/bean/ConversionService/ProperEditorRegistrar注册到beanFactory;

看类图:

所以呢,BeanFactory中的关联的都是Spring bean相关的组建:

Spring context中关联的搜是企业级的组建;

那么Spring context的生命周期是怎么样的呢?

Spring context的生命周期其实可以从ApplicationContextEvent的类型作出推断:

spring framework中的context的生命周期有4个,

1:refresh

2:start

3:stop

4:close

其实在代码中我们默认启动的过程中,只有refresh和close两个生命周期,其余的两个生命周期在单纯的spring framework中应用的不多。在Spring event章节我们也仔细的讲过这部分内容,那这次我们就仔细的梳理以下Spring context的refresh过程。

还是关注Spring的模版类AbstractApplicationContext的主要方法refresh();这个方法是Spring context的生命周期的开始

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 context的refresh其实是一个模版方法,给我们制定了Spring context启动的步骤,不管我们在Spring的web项目中,还是其他Spring框架的工程中,都是围绕这个方法做的扩展,

总体的思路如下:

1:准备环境 prepareRefresh():

2:获取BeanFactory  obtainFreshBeanFactory:ClassPathXmlApplicationContext在refreshBeanFactory的时候加载了configlocation路径上beanDefinition,

3:准备BeanFactory prepareBeanFactory,准备beanFactory,注册比较特殊的几个Bean,比如ClassLoader,PropertyEditorRegisrtrar,Environment LoadTimeWeaver,忽略掉一些不必要的接口实现

4:留给子类扩展BeanFactory:postProcessBeanFactory() 模版方法准备好了BeanFactory,但是留给了子类的拓展接口

5:执行BeanFactoryPostProcessor:invokeBeanFactoryPostProcessors();调用BeanFactoryBeanPostProcessor的实现,来处理BeanFactory,特别的是AnnotationConfigApplicationContext在这个步骤CommonConfigPostProcessor

6:初始化消息源:initMessageSource(),我们在i18章节讲到过

7:初始化事件广播器:initApplicationEventMutilcaster()

8:留给子类扩展 context: onRefresh();在 留给context的子类一个扩展口,来实例化一些特殊作用的bean,

9:注册事件监听器 :registerListener()

10:实例化所有非延迟加载的bean: finishBeanFactoryInitialization(beanFactory);这些bean都是在obtainBeanFactory加载的,在InvokeBeanFactoryPostProcessor时处理的@ComponentScan组建,@Configuration @Import @Bean等新加入的beanDefinition

11:清除上面扫描反射加载等操作的缓存:

12:lifeCycle组建启动

13:广播事件 refreshEvent , 

14:注册MBean

15:重制缓存:finanlly{}模块

整体而言,上面步骤包括了spring framework context 的refresh 生命周期的大部分内容,在Springmvc 或者是Springcloud的应用过程中,这是最为基础的部分,在学习别的服务的过程中,我们可能会充满疑惑,远程配置(apollo或者其他)是什么时候如何更新到应用本地的property的?Springcloud是如何实现rpc的?Mybatis的mapper如何加载成Spring bean的?其实不同的功能都是扩展了上面的refresh方法,让我们实现了很多重要的功能。

spring context的close 生命周期我们就不再细致的讨论了,有兴趣的同学可以通过查看源代码的过程了解一下。

ClassPathXmlApplicationContext的refresh方法

AnnotationConfigApplicationContext的启动

上面就是xml和annotated的refresh过程,建议大图打开。

学习的过程充满矛盾和困惑,但是解决困惑的过程中让我们的知识体系不断的清晰明朗。spring的学习过程尤其如此。Spring设计思想系列的blog更新到此已经算是基本完结了,但是学习的过程刚刚开始。道阻且长,努力加餐。各位一起努力

猜你喜欢

转载自blog.csdn.net/David_lou/article/details/108254899