## 第二十章: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 是如何集成的?