之前的章节讲完了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更新到此已经算是基本完结了,但是学习的过程刚刚开始。道阻且长,努力加餐。各位一起努力