Spring 应用上下文(ApplicationContext),是 Spring 应用的核心接口,也是我们常说的 Spring 容器,除了扩展了基础容器 BeanFactory 还提供了更多企业级的特性,如资源管理、事件发布、国际化等。
前言
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。
点击查看原文,获取更多福利!
https://developer.aliyun.com/article/1086017?utm_content=g_1000365171
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。