本系列大量参考Spring IOC 容器源码分析、 【死磕 Spring】—– IOC 总结、程序员囧辉的CSDN
上一篇说到,向beanFactory
设置了各个beanFactory
所需的功能,执行BeanFactoryPostProcessors
和注册BeanPostProcessors
后。这次简单提到一些国际化组件、事件广播器和事件监听器(自认为这写的并不好,可以略过)。这篇算是水文
文章内容如下:
1.AbstractApplicationContext#refresh()
//初始化国际化组件
2.AbstractApplicationContext#initMessageSource
//初始化事件广播器
3.AbstractApplicationContext#initApplicationEventMulticaster
//在初始化非懒加载的bean之前初始化一下特殊的bean,交由子类实现
4. AbstractApplicationContext#onRefresh()
//注册事件监听器
5. AbstractApplicationContext#registerListeners()
//实例化所有剩余的非懒加载单例 bean(简单介绍)
6. AbstractApplicationContext# finishBeanFactoryInitialization(beanFactory)
1.refresh
public void refresh() throws BeansException, IllegalStateException {
// 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
synchronized (this.startupShutdownMonitor) {
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
// 这块待会会展开说
prepareBeanFactory(beanFactory);
try {
// 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
// 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
initApplicationEventMulticaster();
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
registerListeners();
// 重点,重点,重点
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// 最后,广播事件,ApplicationContext 初始化完成
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.
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
destroyBeans();
// Reset 'active' flag.
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();
}
}
}
2.AbstractApplicationContext#initMessageSource 初始化国际化组件
先来看看initMessageSource
方法
protected void initMessageSource() {
//获取Bean工厂,一般是DefaultListBeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//首先判断beanFactory的BeanDifinition缓存里有没有id为messageSource的BeanDifinition
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
//如果有,则从Bean工厂得到这个bean对象
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
//当父类Bean工厂不为空,并且这个bean对象是HierarchicalMessageSource类型
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
//强转为HierarchicalMessageSource
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
//如果父消息源为空,那么设置一个父消息源
// (如果父类是AbstractApplicationContext,则返回父类的messageSource,否则直接返回一个父类)
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
//如果没有这个id为messageSource的BeanDifinition,新建DelegatingMessageSource类作为messageSource的Bean
//因为DelegatingMessageSource类实现了HierarchicalMessageSource接口,而这个接口继承了MessageSource这个类
//因此实现了这个接口的类,都是MessageSource的子类,因此DelegatingMessageSource也是一个MessageSource
DelegatingMessageSource dms = new DelegatingMessageSource();
//给这个DelegatingMessageSource添加父类消息源
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
//将这个messageSource实例注册到Bean工厂中
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
简单解释下国际化的意义;
假设我们正在开发一个支持多国语言的Web应用程序,要求系统能够根据客户端的系统的语言类型返回对应的界面:英文的操作系统返回英文界面,而中文的操作系统则返回中文界面——这便是典型的i18n国际化问题。
对于有国际化要求的应用系统,我们不能简单地采用硬编码的方式编写用户界面信息、报错信息等内容,而必须为这些需要国际化的信息进行特殊处理。简单来说,就是为每种语言提供一套相应的资源文件,并以规范化命名的方式保存在特定的目录中,由系统自动根据客户端语言选择适合的资源文件。
3.AbstractApplicationContext#initApplicationEventMulticaster 初始化事件广播器
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//首先判断beanFactory的BeanDifinition缓存里有没有id为applicationEventMulticaster的BeanDifinition
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
//如果有,就实例化这个BeanDifinition并赋值给本地的变量applicationEventMulticaster
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
//如果没有,那么就直接创建一个SimpleApplicationEventMulticaster赋值给本地变量
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 并且把这个SimpleApplicationEventMulticaster对象注册到beanFactory的缓存中,id为applicationEventMulticaster
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
我们就可以在其他组件要派发事件,自动注入这个
applicationEventMulticaster
,他可以管理很多个ApplicationListener
对象。并将事件发布给这些监听器。
4. AbstractApplicationContext#onRefresh() 在初始化非懒加载的bean之前初始化一下特殊的bean
onRefresh()
则是一个空方法,交由子类自己实现,在初始化非懒加载的bean之前初始化一下特殊的bean
。(看自己的业务要怎么做啦)
5. AbstractApplicationContext#registerListeners() 注册事件监听器
protected void registerListeners() {
// 获取硬编码进来的ApplicationListeners(指非配置的,通过代码直接添加进来的)
//注册 到我们上面刚初始化的ApplicationEventMulticaster 中。
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
//从容器中获取所有实现了ApplicationListener接口的bd的bdName,注册到ApplicationEventMulticaster 中
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 发布早期 earlyApplicationEvents 事件,到 ApplicationListener 们,默认为空
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
有关Spring的事件机制简单了解可以参考下面这两个链接,有机会再细说。
6. AbstractApplicationContext# finishBeanFactoryInitialization(beanFactory) 实例化所有剩余的非懒加载单例 bean(简单介绍)
上面都是简单介绍,接下来就是主菜了
该方法会实例化所有剩余的非懒加载单例 bean。除了一些内部的 bean、实现了 BeanFactoryPostProcessor
接口的 bean、实现了BeanPostProcessor
接口的 bean(上述的这三类在前面方法里已经被实现了),其他的非懒加载单例bean
都会在这个方法中被实例化,并且 BeanPostProcessor
的触发也是在这个方法中。
这边我们简单介绍下,这篇就简单水一下吧,因为这个方法比较重要,调用栈又特别深,需要开好几个章节来讲。