前言
Spring 应用上下文(ApplicationContext),是 Spring 应用的核心接口,也是我们常说的 Spring 容器,除了扩展了基础容器 BeanFactory 还提供了更多企业级的特性,如资源管理、事件发布、国际化等。理解 Spring 应用上下文的生命周期也就理解了 Spring 内部的运行的核心逻辑,生命周期中同时提供了很多扩展点,跟随文章,我们一探究竟。
应用上下文的生命周期
Spring ApplicationContext 具有层次性的设计,生命周期的管理主要在 AbstractApplicationContext,类图如下。
生命周期的相关方法均由实现的接口提供,各生命周期阶段并非完整的从上而下执行,部分阶段是可选的,具体如下。
刷新阶段:org.springframework.context.ConfigurableApplicationContext#refresh
启动阶段:org.springframework.context.Lifecycle#start
停止阶段:org.springframework.context.Lifecycle#stop
关闭阶段:org.springframework.context.ConfigurableApplicationContext#close
刷新阶段
刷新阶段是 Spring 应用上下文生命周期的主要阶段,刷新阶段完成后 Spring 中的非延迟单例 bean 即实例化完成,依赖注入也完成,可以正常调用 bean 的方法。有关 bean 的生命周期可参考我前面的文章《Java 面试必备的 Spring Bean 生命周期总结》。
刷新阶段对应的 AbstractApplicationContext#refresh 方法源码如下。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 应用上下文刷新准备 prepareRefresh(); // BeanFactory 创建 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // BeanFactory 准备 prepareBeanFactory(beanFactory); try { // BeanFactory 后处理,由子类扩展 postProcessBeanFactory(beanFactory); // BeanFactory 后处理,调用 BeanFactoryPostProcessor 方法 invokeBeanFactoryPostProcessors(beanFactory); // 注册 BeanPostProcessor registerBeanPostProcessors(beanFactory); // 初始化 MessageSource initMessageSource(); // 初始化事件广播器 initApplicationEventMulticaster(); // 上下文刷新 onRefresh(); // 注册事件监听器 registerListeners(); // 初始化完成,实例化所有非延迟初始化的单例 bean finishBeanFactoryInitialization(beanFactory); // 刷新完成 finishRefresh(); } catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
下面对应用上下文的刷新阶段进行细化分析。
上下文刷新准备阶段
上下文刷新准备阶段的工作如下:
设置启动时间及状态标识。
初始化 PropertySource。
由子类进行扩展,web 环境下将初始化名称为 servletContextInitParams 和 servletConfigInitParams 的 PropertySource 。
关于 PropertySource 可参见我前面的文章《Spring 中的 Environment 、Profile 与 PropertySource》。
校验 Environment 中必须的属性。
初始化事件监听器集合。
关于 Spring 事件可参见我前面的文章《Spring 事件处理机制详解,带你吃透 Spring 事件》 。
初始化早期事件集合。
对应的AbstractApplicationContext#prepareRefresh方法源码如下。
protected void prepareRefresh() { // 设置刷新事件及激活状态 this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); ... 省略日志打印代码 // 初始化 Environment 中的 PropertySource,该方法为空方法,由子类实现,如 web 环境下添加 ServletContext 初始化及 Servlet 配置的 PropertySource initPropertySources(); // 校验 Environment 设置的必须的属性 getEnvironment().validateRequiredProperties(); if (this.earlyApplicationListeners == null) { // 首次 fresh,把刷新前添加的监听器添加到 earlyApplicationListeners this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // 再次 fresh,把之前添加的监听器添加到 applicationListeners this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // 初始化事件集合,事件广播器初始化完成后发布 this.earlyApplicationEvents = new LinkedHashSet<>(); }
BeanFactory 创建阶段
BeanFactory 创建阶段的工作如下:
刷新 BeanFactory。
销毁并关闭 BeanFactory,如果已存在。
创建 BeanFactory。
设置 BeanFactory 的 ID。
设置 BeanFactory 是否允许 BeanDefinition 重复注册及循环引用。
关于循环引用,可参见我前面的文章《Spring 循环依赖处理》。
加载 BeanDefinition。
抽象方法,由子类进行实现。XML 和注解方式加载 BeanDefinition 的方式有所不同。
关于 BeanDefinition,可参见我前面的文章《掌握 Spring 必须知道的 BeanDefinition》 。
关联 BeanFactory 到应用上下文。
获取 BeanFactory。
相关的源码说明如下所示。
// AbstractApplicationContext#obtainFreshBeanFactory protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 先创建 BeanFactory,该方法为抽象方法,由子类进行实现 refreshBeanFactory(); // 再获取 BeanFactory return getBeanFactory(); } // AbstractRefreshableApplicationContext#refreshBeanFactory @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { // 如果已经存在 BeanFactory,先销毁 bean ,然后关闭 BeanFactory destroyBeans(); closeBeanFactory(); } try { // 创建 BeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 设置是否允许重复注册 BeanDefinition,是否允许循环引用 customizeBeanFactory(beanFactory); // 加载 BeanDefinition,抽象方法,由子类进行实现 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
BeanFactory 准备阶段
BeanFactory 准备阶段的工作如下:
设置加载 bean class 的 ClassLoader。
设置解析 BeanDefinition 中字符串的表达式处理器。
添加 PropertyEditorRegistrar 的实现 ResourceEditorRegistrar。
添加 Aware 回调接口 BeanPostProcessor 的实现 ApplicationContextAwareProcessor。
支持的 Aware 回调接口包括 EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware。
忽略 Aware 回调接口作为依赖注入接口。
忽略的 Aware 回调接口和上面 ApplicationContextAwareProcessor 支持的 Aware 回调接口相对应,保持一致。
注册 ResolvableDependency 对象作为 bean。
包括 BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext。
添加 BeanPostProcessor 的实现 ApplicationListenerDetector。用于将 ApplicationListener 添加到 ApplicationContext。
如果 BeanFactory 中存在名称为 loadTimeWeaver 的 bean,
添加 BeanPostProcessor 的实现 LoadTimeWeaverAwareProcessor。
设置临时类加载器 ContextTypeMatchClassLoader。
注册单例 bean Environment、Java System Properties、OS 环境变量。
相关的源码说明如下所示:
// AbstractApplicationContext#prepareBeanFactory protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 设置类加载器、表达式处理器;添加 ResourceEditorRegistrar beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 配置 Aware 回调接口的处理器 ApplicationContextAwareProcessor,并且忽略依赖注入对应的 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); // 注册依赖注入时可解析的依赖 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // 添加 ApplicationListenerDetector,用于添加事件监听器到应用上下文 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // AOP 相关 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 后置处理阶段
BeanFactory 后置处理阶段的工作如下:
调用方法 postProcessBeanFactory。
该方法实现为空,由子类进行扩展。
如 web 环境下会设置 ServletContextAware、ServletConfigAware 回调处理,注册 web 环境下的 scope 及相关的 bean。
调用 BeanFactoryPostProcessor 中的后置处理方法。
如果临时 ClassLoader 不存在并且存在名称为 loadTimeWeaver 的 bean,
添加 BeanPostProcessor 的实现 LoadTimeWeaverAwareProcessor。
设置临时类加载器 ContextTypeMatchClassLoader。
相关的源码如下:
// AbstractRefreshableWebApplicationContext#postProcessBeanFactory protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 添加 web 环境下 aware 处理,忽略 aware 依赖注入接口 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); // 注册 web 环境下的 scope WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); // 注册 web 环境下的 bean WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); } // AbstractApplicationContext#invokeBeanFactoryPostProcessors protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 调用 BeanFactoryPostProcessor 处理方法 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // AOP 相关 if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
BeanPostProcessor 注册阶段
BeanPostProcessor 注册阶段的工作主要是将 BeanPostProcessor 类型的 bean 添加到 BeanFactory 内部持有的 BeanPostProcessor 列表中。添加顺序如下:
实现 PriorityOrdered 接口的 BeanPostProcessor。
实现 Ordered 接口的 BeanPostProcessor。
普通的 BeanPostProcessor。
实现 MergedBeanDefinitionPostProcessor 接口的 BeanPostProcessor。
ApplicationListenerDetector 接口。
相关的源码如下:
// AbstractApplicationContext#registerBeanPostProcessors protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }
MessageSource 初始化阶段
MessageSource 初始化阶段用于保证 BeanFactory 中存在 MessageSource 类型的单例 bean。关于 MessageSource,可参见我前面的文章《Spring 国际化支持之 MessageSource》。
相关的源码如下:
protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { // 设置 messageSource 到当前应用上下文 this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // 设置父 MessageSource if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { hms.setParentMessageSource(getInternalParentMessageSource()); } } } else { // 设置 MessageSource 到当前应用上下文,通过调用父 MessageSource 实现其功能 DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); } }
事件广播器初始化阶段
事件广播器初始化阶段主要用来保证应用上下文中存在 ApplicationEventMulticaster。相关的源码如下:
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { // 存在名称为 applicationEventMulticaster 的 bean,设置到应用上下文 this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); } } else { // 不存在 bean,设置到当前应用上下文,并注册为 bean this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); } } }
上下文刷新阶段
上下文刷新阶段对应的方法为AbstractApplicationContext#onRefresh,该方法为空方法,由子类进行实现。
事件监听器注册阶段
事件监听器注册阶段的工作如下:
添加当前应用上下文关联的事件监听器到广播器。
添加 BeanFactory 中注册的事件监听器 bean 到广播器。
广播早期事件。
相关源代码如下:
protected void registerListeners() { // 添加应用上下文中的事件监听器到事件广播器中 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // 添加 BeanFactory 中注册的事件监听器到事件广播器中 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // 发布早期事件 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { // 广播当前应用上下文刷新前发布的事件 getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
BeanFactory 初始化完成阶段
BeanFactory 初始化完成阶段的工作如下:
如果 BeanFactory 中存在注册的名称为 conversionService 的 ConversionService,将其设置到 BeanFactory 中。
如果 BeanFactory 中不存在 StringValueResolver,添加 StringValueResolver 到 BeanFactory。
依赖查找 LoadTimeWeaverAware 接口。
BeanFactory 置空临时类加载器。
BeanFactory 冻结配置。
BeanFactory 实例化非延迟单例 bean。
对应的源代码如下:
// AbstractApplicationContext#finishBeanFactoryInitialization protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. // 初始化当前上下文的 ConversionService 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.setTempClassLoader(null); // 允许缓存所有bean定义元数据,不需要进一步更改。 beanFactory.freezeConfiguration(); // 实例化所有剩余的(非延迟初始化)单例。 beanFactory.preInstantiateSingletons(); }
上下文刷新完成阶段
上下文刷新完成阶段的工作如下:
清除 ResourceLoader 缓存。
初始化 LifecycleProcessor 对象。
调用LifecycleProcessor#onRefresh方法。
发布上下文刷新事件。
向 MBeanServer 托管 Live Beans。
相关的源代码如下:
protected void finishRefresh() { // 清空 ResourceLoader 缓存 clearResourceCaches(); // 初始化 LifecycleProcessor initLifecycleProcessor(); // 调用刷新方法 getLifecycleProcessor().onRefresh(); // 发布上下文刷新事件 publishEvent(new ContextRefreshedEvent(this)); // 向 MBeanServer 托管 Live Beans LiveBeansView.registerApplicationContext(this); }
启动阶段
启动阶段的方法为AbstractApplicationContext#start
,该方法的调用必须在#refresh
方法之后。主要工作如下:
- 调用
LifecycleProcessor#start
法。 - 发布上下文启动事件。
对应的源代码如下。
public void start() { // 需要先获取 LifecycleProcessor,因此必须等 #refresh 方法调用后才能调用该方法 getLifecycleProcessor().start(); publishEvent(new ContextStartedEvent(this)); }
停止阶段
停止阶段和启动阶段相对应,也应在#refresh
方法调用后调用。主要工作如下:
- 调用
LifecycleProcessor#stop
方法。 - 发布上下文关闭事件。
对应的源码如下。
public void stop() { getLifecycleProcessor().stop(); publishEvent(new ContextStoppedEvent(this)); }
关闭阶段
Spring 应用上下文的启动和停止阶段均为可选的生命周期,而关闭阶段可以在停止使用应用上下文后调用。主要的工作如下:
设置上下文状态标识。
Live Beans 撤销 JMX 托管。
发布上下文关闭事件。
调用LifecycleProcessor#onClose关闭 Lifecycle。
销毁 BeanFactory 中的单例 bean。
关闭 BeanFactory。
回调#onClose方法,由子类实现。
移除注册的 JVM 关闭时的 shutdown hook。
相关的源代码如下。
public void close() { synchronized (this.startupShutdownMonitor) { doClose(); // 如果注册了 JVM shutdown hoo 则进行移除。 if (this.shutdownHook != null) { try { Runtime.getRuntime().removeShutdownHook(this.shutdownHook); } catch (IllegalStateException ex) { // ignore - VM is already shutting down } } } } protected void doClose() { // 检查是否需要关闭 if (this.active.get() && this.closed.compareAndSet(false, true)) { // 撤销 JMX 托管 LiveBeansView.unregisterApplicationContext(this); try { // 发布关闭事件 publishEvent(new ContextClosedEvent(this)); } catch (Throwable ex) { logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex); } // 停止所有的 Lifecycle bean if (this.lifecycleProcessor != null) { try { this.lifecycleProcessor.onClose(); } catch (Throwable ex) { logger.warn("Exception thrown from LifecycleProcessor on context close", ex); } } // 销毁 BeanFactory 中的所有单例 bean destroyBeans(); // 关闭 BeanFactory closeBeanFactory(); // 子类扩展的方法 onClose(); // 重置 applicationListeners if (this.earlyApplicationListeners != null) { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // 设置激活标识 this.active.set(false); } }