|
@@ -0,0 +1,363 @@
|
|
|
+## 第二十章:Spring 应用上下文生命周期
|
|
|
+
|
|
|
+### ApplicationContext 接口继承关系
|
|
|
+
|
|
|
+![img](assets/o_201108090206ApplicationContext-16684235113772.png)
|
|
|
+
|
|
|
+### Spring 应用上下文生命周期
|
|
|
+
|
|
|
+- `AbstractApplicationContext#refresh`
|
|
|
+
|
|
|
+ ```java
|
|
|
+ @Override
|
|
|
+ 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 应用上下文启动准备阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#prepareRefresh() 方法
|
|
|
+ - 启动时间 - `startupDate`
|
|
|
+ - 状态标识 - `closed(false)`、`active(true)`
|
|
|
+ - 初始化 PropertySources - initPropertySources()
|
|
|
+ - 默认为空方法,子类可继承
|
|
|
+ - Web 应用上下文继承这个方法,并将 Web 参数初始化为 `PropertySource`
|
|
|
+ - 检验 Environment 中必须属性
|
|
|
+ - `AbstractPropertyResolver#requiredProperties`,默认为空,可设置
|
|
|
+ - 初始化事件监听器集合
|
|
|
+ - `earlyApplicationListeners`
|
|
|
+ - `applicationListeners`
|
|
|
+ - 初始化早期 Spring 事件集合
|
|
|
+ - `earlyApplicationEvents`
|
|
|
+
|
|
|
+### BeanFactory 创建阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#obtainFreshBeanFactory 方法
|
|
|
+ - 抽象方法
|
|
|
+ - 子类实现,AbstractRefreshableApplicationContext#refreshBeanFactory
|
|
|
+ - 刷新 Spring 应用上下文底层 BeanFactory - refreshBeanFactory()
|
|
|
+ - 销毁或关闭 `BeanFactory` ,如果已存在的话
|
|
|
+ - 创建 BeanFactory - createBeanFactory()
|
|
|
+ - `DefaultListableBeanFactory`
|
|
|
+ - 设置 BeanFactory Id
|
|
|
+ - 自定义 `BeanFactory` 属性 - `customizeBeanFactory(beanFactory)`
|
|
|
+ - 设置 “是否允许 BeanDefinition 重复定义” - customizeBeanFactory(DefaultListableBeanFactory)
|
|
|
+ - `AbstractRefreshableApplicationContext#allowBeanDefinitionOverriding`
|
|
|
+ - 默认为 true
|
|
|
+ - 设置 “是否允许循环引用(依赖)” - customizeBeanFactory(DefaultListableBeanFactory)
|
|
|
+ - `AbstractRefreshableApplicationContext#allowCircularReferences`
|
|
|
+ - 默认为 true
|
|
|
+ - 加载 BeanDefinition - loadBeanDefinitions(DefaultListableBeanFactory) 方法
|
|
|
+ - 抽象方法
|
|
|
+ - 关联新建 `BeanFactory` 到 Spring 应用上下文
|
|
|
+- 返回 Spring 应用上下文底层 BeanFactory - getBeanFactory()
|
|
|
+ - 抽象方法
|
|
|
+
|
|
|
+### BeanFactory 准备阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#prepareBeanFactory(ConfigurableListableBeanFactory) 方法
|
|
|
+
|
|
|
+ - 关联 `ClassLoader`
|
|
|
+
|
|
|
+ - 设置 Bean 表达式处理器
|
|
|
+
|
|
|
+ - 与 SpEL 表达式相关
|
|
|
+ - `org.springframework.context.expression.StandardBeanExpressionResolver`
|
|
|
+
|
|
|
+ - 添加 PropertyEditorRegistrar 实现 - ResourceEditorRegistrar
|
|
|
+
|
|
|
+ - `org.springframework.beans.support.ResourceEditorRegistrar`
|
|
|
+
|
|
|
+ - 添加 Aware 回调接口 BeanPostProcessor 实现 - ApplicationContextAwareProcessor
|
|
|
+
|
|
|
+ - `EnvironmentAware`
|
|
|
+ - `EmbeddedValueResolverAware`
|
|
|
+ - `ResourceLoaderAware`
|
|
|
+ - `ApplicationEventPublisherAware`
|
|
|
+ - `MessageSourceAware`
|
|
|
+ - `ApplicationContextAware`
|
|
|
+
|
|
|
+ - 忽略 `Aware` 回调接口作为依赖注入接口
|
|
|
+
|
|
|
+ - 注册 ResolvableDependency 对象 - BeanFactory 、ResourceLoader 、 ApplicationEventPublisher 以及 Applicationcontext
|
|
|
+
|
|
|
+ - `BeanFactory` 是 `ApplicationContext` 关联的 `BeanFactory`
|
|
|
+ - `ResourceLoader`、`ApplicationEventPublisher` 以及 `Applicationcontext` 都是 `ApplicationContext`
|
|
|
+
|
|
|
+ - 添加 BeanPostProcessor - ApplicationListenerDetector
|
|
|
+
|
|
|
+ - 在 `BeanPostProcessor#postProcessAfterInitialization` 阶段,将单例的 `ApplicationListener` 加入 `ApplicationContext`
|
|
|
+
|
|
|
+ - 如果包含 beanName 是 loadTimeWeaver 的 bean,注册 BeanPostProcessor - LoadTimeWeaverAwareProcessor 对象,并设置容器的临时 ClassLoader
|
|
|
+
|
|
|
+ ,AbstractBeanFactory#tempClassLoader
|
|
|
+
|
|
|
+ - 与 AOP 相关
|
|
|
+
|
|
|
+ - 注册单例对象 - Environment、Java System Properties 以及 OS 环境变量
|
|
|
+
|
|
|
+ - `environment` - `ApplicationContext#environment`
|
|
|
+ - `systemProperties` - `(Map) System.getProperties()`
|
|
|
+ - `systemEnvironment` - `(Map) System.getenv()`
|
|
|
+
|
|
|
+### BeanFactory后置处理阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#postProcessBeanFactory(ConfigurableListableBeanFactory) 方法
|
|
|
+
|
|
|
+ - 由子类覆盖该方法
|
|
|
+
|
|
|
+- org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory) 方法
|
|
|
+
|
|
|
+ - 判断 BeanFactory 是不是 BeanDefinitionRegistry 的实例
|
|
|
+
|
|
|
+ - `DefaultListableBeanFactory` 实现 `BeanDefinitionRegistry`
|
|
|
+ - 如果是,调用 BeanFactoryPostProcessor 或 BeanDefinitionRegistryPostProcessor 后置处理方法
|
|
|
+ - `BeanDefinitionRegistryPostProcessor` 继承 `BeanFactoryPostProcessor`
|
|
|
+ - `BeanFactoryPostProcessor#postProcessBeanFactory`
|
|
|
+ - `BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry`
|
|
|
+ - 如果不是,只调用 `BeanFactoryPostProcessor` 后置处理方法 `BeanFactoryPostProcessor#postProcessBeanFactory`
|
|
|
+
|
|
|
+ - 如果包含 beanName 是 loadTimeWeaver 的 bean,注册 BeanPostProcessor - LoadTimeWeaverAwareProcessor 对象,并设置容器的临时 ClassLoader
|
|
|
+
|
|
|
+ ,AbstractBeanFactory#tempClassLoader
|
|
|
+
|
|
|
+ - 与 AOP 相关
|
|
|
+
|
|
|
+执行顺序:
|
|
|
+
|
|
|
+1. 对 BeanDefinitionRegistryPostProcessor 进行处理
|
|
|
+ 1. 执行 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
|
|
|
+ 1. 按照添加顺序执行, `AbstractApplicationContext#beanFactoryPostProcessors` 中的 `BeanDefinitionRegistryPostProcessor`
|
|
|
+ 2. 按照 Order 顺序执行,`BeanFactory` 中实现了 `PriorityOrdered` 的 `BeanDefinitionRegistryPostProcessor` Bean
|
|
|
+ 3. 按照 Order 顺序执行,`BeanFactory` 中实现了 `Ordered` 的 `BeanDefinitionRegistryPostProcessor` Bean
|
|
|
+ 4. 按照 Order 顺序执行,其他 `BeanFactory` 中的 `BeanDefinitionRegistryPostProcessor` Bean
|
|
|
+ 2. 执行 BeanFactoryPostProcessor#postProcessBeanFactory
|
|
|
+ 1. `AbstractApplicationContext#beanFactoryPostProcessors` 中的普通 `BeanFactoryPostProcessor`
|
|
|
+ 2. `BeanFactory` 中 `BeanDefinitionRegistryPostProcessor`
|
|
|
+2. 对 BeanFactoryPostProcessor 继续处理,BeanFactoryPostProcessor#postProcessBeanFactory
|
|
|
+ 1. 按照 Order 顺序执行,实现 `PriorityOrdered` 接口的 `BeanFactoryPostProcessor`
|
|
|
+ 2. 按照 Order 顺序执行,实现 `Ordered` 接口的 `BeanFactoryPostProcessor`
|
|
|
+ 3. 其他常规 `BeanFactoryPostProcessor`
|
|
|
+
|
|
|
+### BeanFactory 注册 BeanPostProcessor 阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#registerBeanPostProcessors(ConfigurableListableBeanFactory) 方法
|
|
|
+ - 注册 `PriorityOrdered` 类型的 `BeanPostProcessor` Beans -- 该bean会提前初始化
|
|
|
+ - 注册 `Ordered` 类型的 `BeanPostProcessor` Beans
|
|
|
+ - 注册普通 `BeanPostProcessor` Beans
|
|
|
+ - 注册 MergedBeanDefinitionPostProcessor Beans
|
|
|
+ - `MergedBeanDefinitionPostProcessor` 继承 `BeanPostProcessor`,生命周期在 MergedBeanDefinition 后
|
|
|
+ - 重新注册 ApplicationListenerDetector 对象
|
|
|
+ - 为了将 `ApplicationListenerDetector` 的顺序放到最后
|
|
|
+
|
|
|
+### 初始化內建 Bean: MessageSource
|
|
|
+
|
|
|
+- AbstractApplicationContext#initMessageSource 方法
|
|
|
+ - 如果 `BeanFactory` 中存在 beanName 为 `messageSource` 的 `MessageSource` ,则使用,否则注册 `DelegatingMessageSource`
|
|
|
+ - 回顾章节 - 第十二章 Spring 国际化 - `MessageSource` 内建依赖
|
|
|
+
|
|
|
+### 初始化內建 Bean: Spring 事件广播器
|
|
|
+
|
|
|
+- AbstractApplicationContext#initApplicationEventMulticaster 方法
|
|
|
+ - 如果 `BeanFactory` 中存在 beanName 为 `applicationEventMulticaster` 的 `ApplicationEventMulticaster` ,则使用,否则注册 `SimpleApplicationEventMulticaster`
|
|
|
+ - 回顾章节 - 第十七章 Spring 事件 - `ApplicationEventPublisher` 底层实现
|
|
|
+
|
|
|
+### Spring 应用上下文刷新阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#onRefresh 方法
|
|
|
+ - 空方法,由子类覆盖该方法
|
|
|
+ - `org.springframework.web.context.support.AbstractRefreshableWebApplicationContext#onRefresh`
|
|
|
+ - `org.springframework.web.context.support.GenericWebApplicationContext#onRefresh`
|
|
|
+ - `org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext#onRefresh`
|
|
|
+ - `org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh`
|
|
|
+ - `org.springframework.web.context.support.StaticWebApplicationContext#onRefresh`
|
|
|
+
|
|
|
+### Spring 事件监听器注册阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#registerListeners 方法
|
|
|
+ - 将 ApplicationListener 添加到 AbstractApplicationContext#applicationEventMulticaster
|
|
|
+ - 添加当前应用上下文所关联的 `ApplicationListener` 对象(集合)
|
|
|
+ - 添加 `BeanFactory` 所注册 `ApplicationListener` Beans
|
|
|
+ - 广播早期 Spring 事件
|
|
|
+ - `AbstractApplicationContext#earlyApplicationEvents`
|
|
|
+
|
|
|
+### BeanFactory 初始化完成阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory) 方法
|
|
|
+
|
|
|
+ - `BeanFactory` 关联 `ConversionService` Bean,如果存在
|
|
|
+
|
|
|
+ - beanName 为 `conversionService` 的 `ConversionService`
|
|
|
+
|
|
|
+ - 添加 `StringValueResolver` 对象
|
|
|
+
|
|
|
+ - 如果 `AbstractBeanFactory#embeddedValueResolvers` 为空,添加一个
|
|
|
+
|
|
|
+ ```java
|
|
|
+ if (!beanFactory.hasEmbeddedValueResolver()) {
|
|
|
+ beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
|
|
|
+ }
|
|
|
+ ```
|
|
|
+
|
|
|
+ - 依赖查找 `LoadTimeWeaverAware` Bean -- AOP
|
|
|
+
|
|
|
+ - `BeanFactory` 临时 `ClassLoader` 置为 `null`
|
|
|
+
|
|
|
+ - `BeanFactory` 冻结配置
|
|
|
+
|
|
|
+ - `DefaultListableBeanFactory#configurationFrozen`
|
|
|
+ - `DefaultListableBeanFactory#frozenBeanDefinitionNames`
|
|
|
+
|
|
|
+ - `BeanFactory` 初始化非延迟单例 Beans
|
|
|
+
|
|
|
+ 1. 初始化非延迟单例 Bean
|
|
|
+ 2. 触发单例 Bean 中的 `SmartInitializingSingleton` 的生命周期, `SmartInitializingSingleton#afterSingletonsInstantiated`
|
|
|
+
|
|
|
+### Spring 应用上下文刷新完成阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#finishRefresh 方法
|
|
|
+ - 清除 `ResourceLoader` 缓存 - `clearResourceCaches()` @since 5.0
|
|
|
+ - 初始化 LifecycleProcessor 对象 - initLifecycleProcessor()
|
|
|
+ - 如果不存在 beanName 为 `lifecycleProcessor` 的 `LifecycleProcessor`,则使用 `DefaultLifecycleProcessor`
|
|
|
+ - 调用 `LifecycleProcessor#onRefresh()` 方法
|
|
|
+ - 发布 Spring 应用上下文已刷新事件 - `ContextRefreshedEvent`
|
|
|
+ - 向 `MBeanServer` 托管 Live Beans
|
|
|
+
|
|
|
+### Spring 应用上下文启动阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#start() 方法
|
|
|
+ - 启动 LifecycleProcessor
|
|
|
+ - 依赖查找 `Lifecycle` Beans
|
|
|
+ - 启动 `Lifecycle` Beans
|
|
|
+- 发布Spring应用上下文已启动事件 - `ContextStartedEvent`
|
|
|
+
|
|
|
+### Spring 应用上下文停止阶段
|
|
|
+
|
|
|
+- AbstractApplicationContext#stop() 方法
|
|
|
+ - 停止 `LifecycleProcessor`
|
|
|
+ - 依赖查找 `Lifecycle` Beans
|
|
|
+ - 停止 `Lifecycle` Beans
|
|
|
+- 发布 Spring 应用上下文已停止事件 - `ContextStoppedEvent`
|
|
|
+
|
|
|
+### Spring 应用上下文关闭阶段
|
|
|
+
|
|
|
+- `AbstractApplicationContext#close()` 方法
|
|
|
+- 状态标识:`active(false)`、`closed(true)`
|
|
|
+- Live Beans JMX 撤销托管
|
|
|
+ - `LiveBeansView#unregisterApplicationContext(ConfigurableApplicationContext)`
|
|
|
+- 发布 Spring 应用上下文已关闭事件 - `ContextCLosedEvent`
|
|
|
+- 关闭 LifecycleProcessor
|
|
|
+ - 依赖查找 `Lifecycle` Beans
|
|
|
+ - 停止 `Lifecycle` Beans
|
|
|
+- 销毁 Spring Beans
|
|
|
+- 关闭 `BeanFactory`
|
|
|
+- 回调 `onClose()`
|
|
|
+- 注册 Shutdown Hook 线程(如果曾注册)
|
|
|
+
|
|
|
+## 面试题
|
|
|
+
|
|
|
+#### Spring 应用上下文生命周期有哪些阶段?
|
|
|
+
|
|
|
+- 刷新阶段 - `ConfigurableApplicationContext#refresh()`
|
|
|
+- 启动阶段 - `ConfigurableApplicationContext#start()`
|
|
|
+- 停止阶段 - `ConfigurableApplicationContext#stop()`
|
|
|
+- 关闭阶段 - `ConfigurableApplicationContext#close()`
|
|
|
+
|
|
|
+#### Spring 应用上下文生命周期执行动作?
|
|
|
+
|
|
|
+## 课程加餐内容讨论
|
|
|
+
|
|
|
+### 为什么说 ObjectFactory 提供的是延迟依赖查找?
|
|
|
+
|
|
|
+- 原因
|
|
|
+ - `ObjectFactory` (或 `ObjectProvider` )可关联某一类型 Bean
|
|
|
+ - `ObjectFactory` 和 `ObjectProvider` 对象在被依赖注入和依赖查询时并未实时查找关联类型的 Bean
|
|
|
+ - `ObjectFactory` (或 `ObjectProvider` )调用 `getObject()` 方法时,目标 Bean 才被依赖查找
|
|
|
+- 总结
|
|
|
+ - `ObjectFactory` (或 `ObjectProvider` )相当于某一类型 Bean 依赖查找代理对象
|
|
|
+
|
|
|
+### 依赖查找(注入)的Bean会被缓存吗?
|
|
|
+
|
|
|
+- 单例 Bean (Singleton) - 会
|
|
|
+ - 缓存位置:`org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonObjects` 属性
|
|
|
+- 原型 Bean (Prototype) - 不会
|
|
|
+ - 当依赖查询或依赖注入时,根据 `BeanDefinition` 每次创建
|
|
|
+- 其他 Scope Bean
|
|
|
+ - request : 每个 ServletRequest 内部缓存,生命周期维持在每次HTTP请求
|
|
|
+ - session : 每个 HttpSession 内部缓存,生命周期维持在每个用户HTTP会话
|
|
|
+ - application : 当前 Servlet 应用内部缓存
|
|
|
+
|
|
|
+#### @Bean 的处理流程是怎样的?
|
|
|
+
|
|
|
+- 解析范围 - Configuration Class 中的 `@Bean` 方法
|
|
|
+- 方法类型 - 静态 `@Bean` 方法和实例 `@Bean` 方法
|
|
|
+
|
|
|
+#### BeanFactory是如何处理循环依赖的?
|
|
|
+
|
|
|
+- 循环依赖开关(方法)- `AbstractAutowireCapableBeanFactory#setAllowCircularReferences`
|
|
|
+- 单例工程(属性)- `DefaultSingletonBeanRegistry#singletonFactories`
|
|
|
+- 获取早期未处理 Bean (方法)- `AbstractAutowireCapableBeanFactory#getEarlyBeanReference`
|
|
|
+- 早期未处理 Bean (属性)- `DefaultSingletonBeanRegistry#earlySingletonObjects`
|
|
|
+
|
|
|
+#### MyBatis 与 Spring Framework 是如何集成的?
|