这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
作为spring 容器中很重要的一个容器ApplicationContext 重要程度: 可以给五颗星了!!! 宏观了解:
ApplicationContext 相比较 BeanFactory 扩展的实在是太多了.ApplicationContext 不仅继承了 BeanFactory 的两个扩展接口,还继承了其它几个接口
| Feature | BeanFactory | ApplicationContext |
|---|---|---|
| Bean instantiation/wiring —— Bean的实例化和属性注入 | Yes | Yes |
| Integrated lifecycle management —— 生命周期管理 | No | Yes |
Automatic BeanPostProcessor registration —— Bean后置处理器的支持 | No | Yes |
Automatic BeanFactoryPostProcessor registration —— BeanFactory后置处理器的支持 | No | Yes |
Convenient MessageSource access (for internalization) —— 消息转换服务(国际化) | No | Yes |
Built-in ApplicationEvent publication mechanism —— 事件发布机制(事件驱动) | No | Yes |
概括:ApplicationContext 提供:
- 用于访问应用程序组件的 Bean 工厂方法。继承自
ListableBeanFactory。 - 以通用方式加载文件资源的能力。继承自
ResourceLoader接口。 - 能够将事件发布给注册的监听器。继承自
ApplicationEventPublisher接口。 - 解析消息的能力,支持国际化。继承自
MessageSource接口。 - 从父上下文继承。在子容器中的定义将始终优先。例如,这意味着整个 Web 应用程序都可以使用单个父上下文,而每个 servlet 都有其自己的子上下文,该子上下文独立于任何其他 servlet 的子上下文。
微观解读: 这里做一下介绍,并选取里面最重要的方法 #refersh 解读下: 共有12个方法,一开始看着头大,看的多了自然就会记下来了
// AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新上下文环境
prepareRefresh();
// 创建并初始化 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 填充BeanFactory功能
prepareBeanFactory(beanFactory);
try {
// 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
postProcessBeanFactory(beanFactory);
// 激活各种BeanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截Bean创建的Bean处理器,即注册 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 初始化上下文中的资源文件,如国际化文件的处理等
initMessageSource();
// 初始化上下文事件广播器
initApplicationEventMulticaster();
// 给子类扩展初始化其他Bean
onRefresh();
// 在所有bean中查找listener bean,然后注册到广播器中
registerListeners();
// 初始化剩下的单例Bean(非延迟加载的)
finishBeanFactoryInitialization(beanFactory);
// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经创建的Bean
destroyBeans();
// 重置容器激活标签
cancelRefresh(ex);
// 抛出异常
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
AbstractApplicationContext【掌握*】
这个类是 ApplicationContext 最最最最核心的实现类,没有之一。AbstractApplicationContext 中定义和实现了绝大部分应用上下文的特性和功能
首先有始有终,有准备就有结束,所以第一个方法是prepareRefresh(),最后一个方法是finishRefresh 了解一下准备工作:
1.prepareRefresh: 初始化上下文环境,对系统的环境变量或者系统属性进行准备和校验,如环境变量中必须设置某个值才能运行,否则不能运行
12.finishRefresh : 完成刷新过程,通知生命周期处理器 lifecycleProcessor 刷新过程,同时发出 ContextRefreshEvent 通知别人
2.obtainFreshBeanFactory这个也蛮重要的,简单来说是创建并初始化 BeanFactory,加载配置文件并解析的动作就在这里面 ,包含了刷新BeanFactory ,然后获取 重点了解其中的#loadBeanDefinitions
protected final void refreshBeanFactory() throws BeansException {
// 存在BeanFactory则先销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
// 【1.3】加载配置文件
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
} // catch
}
loadBeanDefinitions往下读下去就是# XmlBeanDefinitionReader加载配置文件,#doLoadBeanDefinitions - 读取配置文件,# parseBeanDefinitions - 解析xml,解析各种标签
-
prepareBeanFactory 填充BeanFactory的功能
-
postProcessBeanFactory()
-
invokeBeanFactoryPostProcessors()
-
registerBeanPostProcessors 即注册 BeanPostProcessortodo 这个值得细解
-
initMessageSource 初始化上下文中的资源文件,如国际化文件的处理等
-
initApplicationEventMulticaster 初始化上下文事件广播器
-
onRefresh 给子类扩展初始化其他Bean
-
registerListeners 在所有 bean 中查找 listener bean,然后注册到广播器中
11.finishBeanFactoryInitialization 初始化剩下的单例Bean(非延迟加载的),其中有最最关键的初始化bean的动作,实际上执行了getBean的doGetBean方法,其中包含了循环依赖的判断,这个之后在解析
小结 :
首先 ClassPathXmlApplicationContext 在 refresh 之前,会指定传入的 xml 配置文件的路径,执行 refresh 方法时,会初始化 BeanFactory ,触发 xml 配置文件的读取、加载和解析。其中 xml 的读取需要借助 XmlBeanDefinitionReader ,解析 xml 配置文件则使用 DefaultBeanDefinitionDocumentReader ,最终解析 xml 中的元素,封装出 BeanDefinition ,最后注册到 BeanDefinitionRegistry ,这个就是第一章所讲的容器BeanDefinition 的过程
bean “实例阶段”的生命周期包含步骤:
- bean 的实例化
- 属性赋值 + 依赖注入
- bean 的初始化生命周期回调
- bean 实例的销毁
在所有非延迟加载的单实例 bean 初始化之前,会先初始化所有的 BeanPostProcessor 。
在 ApplicationContext 的 refresh 方法中,finishBeanFactoryInitialization 步骤会初始化所有的非延迟加载的单实例 bean 。实例化 bean 的入口是 getBean → doGetBean ,该阶段会合并 BeanDefinition ,并根据 bean 的 scope 选择实例化 bean 的策略。
创建 bean 的逻辑会走 createBean 方法,该方法中会先执行所有 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法尝试创建 bean 实例,如果成功创建,则会直接调用 postProcessAfterInitialization 方法初始化 bean 后返回;如果 InstantiationAwareBeanPostProcessor 没有创建 bean 实例,则会调用 doCreateBean 方法创建 bean 实例。在 doCreateBean 方法中,会先根据 bean 的 Class 中的构造器定义,决定如何实例化 bean ,如果没有定义构造器,则会使用无参构造器,反射创建 bean 对象
这里只讲了第一部分哦