Spring应用上下文生命周期整体分成四个阶段

  • ConfigurableApplicationContext#refresh,加载或者刷新持久化配置
  • ConfigurableApplicationContext#start,启动应用上下文
  • ConfigurableApplicationContext#stop,停止应用上下文
  • ConfigurableApplicationContext#close,关闭应用上下文,释放锁定资源

实际上refresh执行完成后Spring应用上下文从广义上来说已经启动了,start回调用LifeCycleProcessors的start方法,可以理解refresh处理Spring应用上下文启动需要的东西,start相当于是一个扩展,close和stop是和refresh和close类似的逆向操作。

因此Spring应用上下文生命周期重头戏是refresh和close两个方法对应的实现。

refresh-刷新应用上下文

整个refresh阶段代码如下所示:

从代码可以看出,refresh整体分为以下几个阶段:

  • 准备刷新阶段: prepareRefresh
  • BeanFactory创建阶段: obtainFreshBeanFactory
  • BeanFactory准备阶段: prepareBeanFactory
  • BeanFactory后置处理阶段: postProcessBeanFactory、invokeBeanFactoryPostProcessors
  • BeanFactory注册BeanPostProcessor阶段: registerBeanPostProcessors
  • 初始化内建Bean: initMessageSource、initApplicationEventMulticaster
  • Spring应用上下文刷新阶段: onRefresh
  • Spring事件监听器注册阶段: registerListener
  • BeanFactory初始化完成阶段: finishBeanFactoryInitialization
  • Spring应用上下文刷新完成阶段: finishRefresh

准备刷新阶段

prepareRefresh方法注释如下所示,可以看出,这个方法主要做了三件事来准备上下文刷新:

  • 设置启动时间
  • 设置激活标
  • 执行任何初始化属性来源

    protected void prepareRefresh() {
//设置启动时间、激活标
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true); if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
} //初始化属性源,扩展用
initPropertySources(); //校验必要属性
getEnvironment().validateRequiredProperties(); //创建存储早期applicationListeners容器
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
} //创建存储早期applicationEvents容器,存储早期Spring Application事件,用于后面applicationEventMulticaster发布事件用
this.earlyApplicationEvents = new LinkedHashSet<>();
}

BeanFactory创建阶段

在AbstractRefreshableApplicationContext的refreshBeanFactory实现里,会对这个应用上下文的底层BeanFactory做一个刷新,如果之前有BeanFactory,会先停止,再初始化一个新的BeanFactory

    protected final void refreshBeanFactory() throws BeansException {
     //如果有BeanFactory,先关掉这个BeanFactory  
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
       //创建新的BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
       //设置BeanFactory的id
beanFactory.setSerializationId(getId());
       //设置是否允许BeanDefinition覆盖、是否允许循环依赖
customizeBeanFactory(beanFactory);
       //加载BeanDefinition
loadBeanDefinitions(beanFactory);
       //设置新的BeanFactory为当前应用上下文IoC容器
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

BeanFactory准备阶段

配置容器上下文特征,例如上下文的ClassLoader和后置处理器。

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置容器使用的类加载器: ClassLoader,默认是线程上下文类设置的加载器
beanFactory.setBeanClassLoader(getClassLoader());
     //设置Bean表达式处理器,指定bean definition中的表达是值的解析策略
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
     //添加PropertyEditorRegistrar实现,存储ResourceLoader和PropertyResolver
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); //添加BeanPostProcessor实现,用于处理ApplicationContext的Aware回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
     //忽略指定接口作为依赖注入接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //注册ResolvableDependency,这部分可以被依赖注入但不能被依赖查找
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this); //注册ApplicationListener探测器,如果一个Bean实现了ApplicationListener接口会被当作ApplicationListener注册到Publisher
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //注册动态织入后置处理器
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
} //注册环境Bean单例对象
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

BeanFactory后置处理阶段

postProcessBeanFactory和invokeBeanFactoryPostProcessors都是Spring提供的扩展方式。

postProcessBeanFactory在AbstractApplicationContext里没有实际实现,postProcessBeanFactory注释如下:

可以看出这时Spring应用上下文内部BeanFactory已经标准初始化完成,这时所有Bean的BeanDefinition已经被加载进来,但是还没有被实例化,这时允许继承类注册特殊的BeanPostProcessors等内容。

invokeBeanFactoryPostProcessors方法注释如下:

这个方法会实例化并且执行所有被注册的BeanFactoryPostProcessor的Bean,如果给定显示顺序,按显示顺序执行,invokeBeanFactoryPostProcessors代码如下:

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
     //处理BeanFactoryPostProcessors,这里细节挺多的,要按一定顺序执行BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry和BeanFactoryPostProcessor#postProcessBeanFactory
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); //添加LoadTimeWeaverAwareProcessor
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}

BeanFactory注册BeanPostProcessor

registerBeanPostProcessors方法注释如下:

这个方法的作用就是实例化并且注册所有BeanPostProcessor的Bean,会按给定顺序注册。

这里注册的顺序是:

  • 先注册实现PriorityOrdered的BeanPostProcessor的Bean
  • 再注册实现Ordered的BeanPostProcessor的Bean
  • 然后注册普通的BeanPostProcessor的Bean
  • 后面注册MergedBeanDefinitionPostProcess的Bean
  • 最后注册ApplicationListenerDetector的Bean

初始化内建Bean

初始化内建Bean会初始化两个Bean: MessageSource和ApplicationEventMulticaster。

这两个实现比较类似,都是判断当前BeanFactory(不判断父BeanFactory)是否包含对应Bean,如果不包含,就创建并且用registerSingleton方法注册到BeanFactory。

Spring应用上下文刷新阶段

onRefresh方法注释如下所示:

onRefresh方法是个可以被子类覆盖的模板方法,可以在实例化单例前初始化特殊的Bean。

Spring事件监听器注册阶段

registerListeners方法注释如下所示:

registerListeners方法会把实现ApplicationListener的Bean和非Bean对象注册到ApplicationEventMulticaster。

registerListeners方法代码如下:

    protected void registerListeners() {
//注册非Bean的ApplicationListener实现类的对象
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
} //注册ApplicationListener实现类对应的Bean
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
} //发送早期ApplicationEvent事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}

BeanFactory初始化完成阶段

finishBeanFactoryInitialization方法注释如下所示:

这个方法会结束Spring应用上下文的BeanFactory的初始化,初始化所有剩余的单例Bean。

finishBeanFactoryInitialization方法代码如下所示:

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//如果BeanFactory有ConversionService对象,关联到BeanFactory
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
} //添加StringValueResolver对象
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
} //依赖查找LoadTimeWeaverAware的Bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
} //BeanFactory临时ClassLoader置为null
beanFactory.setTempClassLoader(null); //BeanFactory冻结配置
beanFactory.freezeConfiguration(); //实例化所有不是懒加载的单例对象
beanFactory.preInstantiateSingletons();
}

Spring应用上下文刷新完成阶段

finishRefresh方法注释如下所示:

finishRefresh方法结束Spring应用上下文刷新,调用LifecycleProcessor#onRefresh方法并且发送ContextRefreshedEvent。

finishRefresh方法代码如下所示:

    protected void finishRefresh() {
//清除ResourceLoader缓存
clearResourceCaches(); //初始化LifecycleProcessor对象
initLifecycleProcessor(); //调用LifecycleProcessor#onRefresh方法
getLifecycleProcessor().onRefresh(); //发布Spring应用上下文已刷新事件
publishEvent(new ContextRefreshedEvent(this)); //向MBeanServer托管Live Bean
LiveBeansView.registerApplicationContext(this);
}

start-启动应用上下文

start方法代码如下所示:

    public void start() {
     //启动LifecycleProcessor
getLifecycleProcessor().start();
     //发布应用上下文启动事件
publishEvent(new ContextStartedEvent(this));
}

stop-停止应用上下文

stop方法代码如下所示:

    public void stop() {
     //停止LifecycleProcessor
getLifecycleProcessor().stop();
     //发布应用上下文停止事件
publishEvent(new ContextStoppedEvent(this));
}

close-关闭应用上下文

    protected void doClose() {
//检查激活标
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
       //Live Bean注销托管
LiveBeansView.unregisterApplicationContext(this); try {
//发布Spring应用上下文已关闭事件
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
} //关闭LifecycleProcessor
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
} //销毁Spring Bean
destroyBeans(); //关闭BeanFactory
closeBeanFactory(); //回调onClose
onClose(); //重置本地监听者
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
} //激活标设置为没激活
this.active.set(false);
}
}

Spring应用上下文生命周期的更多相关文章

  1. Spring Bean的生命周期(非常详细)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...

  2. Spring Bean的生命周期,《Spring 实战》书中的官方说法

    连着两天的面试 ,都问到了 Spring 的Bean的生命周期,其中还包括 昨晚一波阿里的电话面试.这里找到了Spring 实战中的官方说法.希望各位要面试的小伙伴记住,以后有可能,或者是有时间 去看 ...

  3. Spring学习手札(四)谈谈Spring Bean的生命周期及作用域

    在Spring中,那些组成应用程序的主体以及由Spring IoC容器所管理的对象,被称之为Bean.Bean与应用程序中其他对象(比如自己创建类)的区别就是,Bean是由IoC容器创建于销毁的.在S ...

  4. Spring Bean的生命周期详解(转)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...

  5. Spring5源码解析-论Spring DispatcherServlet的生命周期

    Spring Web框架架构的主要部分是DispatcherServlet.也就是本文中重点介绍的对象. 在本文的第一部分中,我们将看到基于Spring的DispatcherServlet的主要概念: ...

  6. Spring动态代理及Spring Bean的生命周期

    数组添加值 public class DiTest { /** * 数组 */ private String [] arrays; /** * List:集合 */ private List<I ...

  7. spring bean的生命周期

    掌握好spring bean的生命周期,对spring的扩展大有帮助.  spring bean的生命周期(推荐看)  spring bean的生命周期

  8. Spring Bean的生命周期相关博客

    最近得面试题一直 问 Spring 得生命周期,鉴于自己还未阅读过源码 所以只能是自己 背一波了.属实不懂硬背得作用,但是无奈被各位面试官打败了.等以后有时间了 一定要阅读几遍spring的 源码 有 ...

  9. Spring(三)--Spring bean的生命周期

    Spring bean的生命周期 ApplicationContext Bean生命周期流程 1.需要的实体类 ackage com.xdf.bean; import org.springframew ...

随机推荐

  1. Vue的核心思想

    Vue的核心思想主要分为两部分: 1.数据驱动  2.组件系统 1.数据驱动 在传统的前端交互中,我们是通过Ajax向服务器请求数据,然后手动的去操作DOM元素,进行数据的渲染,每当前端数据交互变化时 ...

  2. 如何封装Promise对象?

    最近看到了一个有趣的Promise的方法,这里记录下来 <script> class MyPromise { constructor(executor) { // 初始化state赋值为p ...

  3. Java语法糖详解

    语法糖 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更 ...

  4. centos系统磁盘扩容

    1.查看磁盘空间大小,使用df -h 命令. 2. 增加磁盘空间,例如下图使用VM虚拟机增加的方式.物理机直接安装挂载上去. 3. 使用fdisk /dev/sda, 创建新分区. 4.重启Linux ...

  5. mysqldump 内存消耗

    MySQL :: MySQL 8.0 Reference Manual :: 4.5.4 mysqldump - A Database Backup Program https://dev.mysql ...

  6. JVM 详解,大白话带你认识 JVM

    前言 如果在文中用词或者理解方面出现问题,欢迎指出.此文旨在提及而不深究,但会尽量效率地把知识点都抛出来 一.JVM的基本介绍 JVM 是 Java Virtual Machine 的缩写,它是一个虚 ...

  7. LOJ10015扩散

    10015. 「一本通 1.2 练习 2」扩散   题目描述 一个点每过一个单位时间就会向 4 个方向扩散一个距离,如图所示:两个点 a .b 连通,记作e(a,b) ,当且仅当 a.b 的扩散区域有 ...

  8. 如何使用Conda源快速安装PyTorch?

    数据科学交流群,群号:189158789,欢迎各位对数据科学感兴趣的小伙伴的加入! 1.切换国内源 1.1.在家目录生成.condarc conda config --set show_channel ...

  9. HTML5 初学者一步一步攀爬 努力加油学习

    Html 5 Html:Hyper Text MarKup Language超文本标签语言 Html:网页的源码 浏览器:"解释和执行"HTMl源码的工具 Head 标签内的信息用 ...

  10. 封装各种生成唯一性ID算法的工具类

    /** * Copyright (c) 2005-2012 springside.org.cn * * Licensed under the Apache License, Version 2.0 ( ...