当前位置:网站首页>第九篇 ApplicationContext初始化
第九篇 ApplicationContext初始化
2022-08-04 05:33:00 【FA-117】
文章目录
前言
前面几篇文章,我们已经聊完了BeanFactory相关内容。但是在日常工作中,我们打交道更多的还是ApplicationContext,站在使用者角度,ApplicationContext更接近实际业务。后续的内容围绕ApplicationContext存在的必要性,以及具体的职责展开,帮助你更好地理解。
一、必要性
我们知道BeanFactory是Bean的Factory,其中完成了BeanDefinition注册,Bean实例的初始化,以及Bean实例的缓存。但是就业务开发而言,纵然我们是OOP的,系统除了直接相关业务对象外,还有各种配置参数,还有必要的外部扩展点预留,还有支撑业务对象外的其他辅助对象。比如,BeanDefinition注册之前,得先找到class,并创建对应的BeanDefinition,然后才能注册。再比如,整个应用的BeanFactory初始化完成后,我们需要做一些后处理工作。一句话总结,BeanFactory用得好,还得基建做的好(高铁跑的快除了动力从集中变分布式,还有配套的铁轨,信号控制,车辆调度,司机,甚至站台)。Spring中完成这些外部功能和BeanFactory嫁接工作的就是ApplicationContext。
二、基本思路
ApplicationContext内部持有BeanFactory的对象,并对外暴露必要的方法。至于获取Bean实例等操作,是对BeanFactory相关对象的简单封装。这里ApplicationContext实际上代理并增强了BeanFactory,因此算是个代理模式。其次,由于两者也是需要紧密耦合的,算是一个静态代理,完全定制化的代理。
三、初始化过程
ApplicationContext初始化,核心是refresh方法
AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备refresh
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备使用的beanFactory
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 注册BeanFactoryPostProcessor
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 调用BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化MessageSource
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 扩展点
onRefresh();
// Check for listener beans and register them.
// 注册上下文相关的Listener
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化BeanFactory中非lazy-init的单例
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();
}
}
}
整体来说整个refresh过程分为三个阶段,A、prepareRefresh, B、onRefresh和 C、finishRefresh。具体的逻辑可以概括为5部分,A,AB,B,BC,C;
1、prepareRefresh
完成启动状态和激活状态标志位重置,初始化自定义属性配置。此处可以做必要扩展,比如生产,测试,开发不同环境中,通过已有参数转换得到另外一些参数,以及对一些参数解析的校验。
2、prepareRefresh - onRefresh
这部分主要是完成BeanFactory初始化,和事件机制初始化。
a、BeanFactory初始化
- 获取BeanFactory实例;
- 注册BeanFactoryPostProcessor;
- 调用BeanFactoryPostProcessor;
- 注册BeanPostProcessor;
b、事件机制
- 事件内容的国际化支持,因此需要初始化MessageSource;
- 初始化事件的广播器,也就是事件的发布者,ApplicationEventMulticaster;
这里想多说的是,Spring中支持业务的那些Bean也是被注册在BeanFactory中的,不过这些Bean的BeanName是在框架层面定义的。
3、onRefresh
Spring留给ApplicationContext子类的一个扩展方法。我们要注意的是,这个方法被调用的时机是在BeanFactory初始化完成后,在Bean实例化之前。
4、onRefresh - finishRefresh
- 注册ApplicationEventListener,还记得前面的事件机制么;
- 设置ConversionService;
- 设置EmbedValueResolver;
- 如果启用了LoadTimeWeaver此时需要把临时的类加载器设置为NULL,以方便垃圾回收;
- 冻结BeanFactory的Configuration,后面不允许再调整BeanFactory;
- 开始初始化BeanFactory中非lazy-init的单例Bean;
5、finishRefresh
本阶段清理之前缓存的资源,发布最终的ContextRefreshedEvent。当然,为了方便管理还注册到了LiveBeansView MBean。
四、总结
`
这里对ApplicationContext的初始化过程做了浅层次的探讨,了解该过程帮助我们在日常工作中排查问题。
边栏推荐
猜你喜欢
Janus转发丢包导致音视频不同步原因分析
关于gopher协议的ssrf攻击
【HIT-SC-MEMO3】哈工大2022软件构造 复习笔记3
Question 1000: Input two integers a and b, calculate the sum of a+b, this question is multiple sets of test data
【HIT-SC-LAB2】哈工大2022软件构造 实验2
Chapter One Introduction
arm learning-1-development board
JUC锁框架——初识AQS
LeetCode_Nov_5th_Week
文件编辑器
随机推荐
通用解决端口占用问题
gRPC intro 1:RPC
文件权限管理 ugo
0--100的能被3整出的数的集合打乱顺序
ZYNQ之FPGA LED 灯闪烁实验
【HIT-SC-MEMO3】哈工大2022软件构造 复习笔记3
JUC锁框架——CountDownLatch、CyclicBarrier和Semaphore
动态内存管理-C语言
用chrome dev tools 强制js注入
Fabric v1.1 环境搭建
跑跑飞弹室外跑步AR游戏代码方案设计
Miscellaneous [development] [VS Code] remote - SSD retry failed
IDEA创建Servlet步骤
Implementation of CAS lock-free queue
SSO单点登陆
让src文件夹能读取xml文件
并发概念基础:线程,死锁
把DocumentsandSettings迁移到别的盘
关于网络安全行业你知道多少?
LeetCode刷题