Spring 源码之九 finishRefresh 详解
公众号搜寻【程序员田同学】,专职程序员兼业余写手,生存不止于写代码
Spring IoC 的核心内容要收尾了,本文将对最初一个办法 finishRefresh 进行介绍,位于 refresh 办法中的第九个地位。
本章理论是对公布订阅模式的一种补充,这是 Spring 在刷新事件实现后公布事件。
因为存在上下文关系,本文也会对 initApplicationEventMulticaster 办法、registerListeners 办法进行回顾。
咱们回到 refresh 办法中。
@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//1、刷新前的筹备
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//2、将会初始化 BeanFactory、加载 Bean、注册 Bean
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//3、设置 BeanFactory 的类加载器,增加几个 BeanPostProcessor,手动注册几个非凡的 bean
prepareBeanFactory(beanFactory);
try {
//4、模板办法
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 执行 BeanFactory 后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 5、Register bean processors that intercept bean creation.
// 注册 bean 后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 国际化
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件播送器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//6、模板办法 --springboot 实现了这个办法
onRefresh();
// Check for listener beans and register them.
//7、注册监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//8、实现 bean 工厂的初始化 ** 办法重要 **********************************************
finishBeanFactoryInitialization(beanFactory);
//9、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();}
}
}
咱们首先晓得这个三个办法的作用:
initApplicationEventMulticaster():初始化利用的事件播送器
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 1. 判断 BeanFactory 是否曾经存在事件播送器(固定应用 beanName=applicationEventMulticaster)if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
// 1.1 如果曾经存在,则将该 bean 赋值给 applicationEventMulticaster
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 1.2 如果不存在,则应用 SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
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() + "]");
}
}
}
最终只做了一件事,初始化利用的事件播送器。(具体什么是事件播送器及其作用可见上上篇文章,具体就不在吃赘述了)
registerListeners():注册监听器。 见上上篇文章
finishRefresh():实现上下文的刷新工作, 本文重点 。
首先概览 finishRefresh 办法
protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).
// 革除资源缓存
clearResourceCaches();
// Initialize lifecycle processor for this context.
// // 1. 为此上下文初始化生命周期处理器
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 2. 首先将刷新结束事件流传到生命周期处理器(触发 isAutoStartup 办法返回 true 的 SmartLifecycle 的 start 办法)getLifecycleProcessor().onRefresh();
// Publish the final event.
// 3. 推送上下文刷新结束事件到相应的监听器
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
1、2、3 是重点内容
1. 为此上下文初始化生命周期处理器
protected void initLifecycleProcessor() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 1. 判断 BeanFactory 是否曾经存在生命周期处理器(固定应用 beanName=lifecycleProcessor)if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
// 1.2 如果不存在,则应用 DefaultLifecycleProcessor
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
// 并将 DefaultLifecycleProcessor 作为默认的生命周期处理器,注册到 BeanFactory 中
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No'" + LIFECYCLE_PROCESSOR_BEAN_NAME + "'bean, using" +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
2. 首先将刷新结束事件流传到生命周期处理器
private void startBeans(boolean autoStartupOnly) {
// 1. 获取所有的 Lifecycle bean
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
// 将 Lifecycle bean 按阶段分组,阶段通过实现 Phased 接口失去
Map<Integer, LifecycleGroup> phases = new HashMap<>();
// 2. 遍历所有 Lifecycle bean,按阶段值分组
lifecycleBeans.forEach((beanName, bean) -> {
// autoStartupOnly=true 代表是 ApplicationContext 刷新时容器主动启动;autoStartupOnly=false 代表是通过显示的调用启动
// 3. 当 autoStartupOnly=false,也就是通过显示的调用启动,会触发全副的 Lifecycle;// 当 autoStartupOnly=true,也就是 ApplicationContext 刷新时容器主动启动,只会触发 isAutoStartup 办法返回 true 的 SmartLifecycle
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
// 3.1 获取 bean 的阶段值(如果没有实现 Phased 接口,则值为 0)int phase = getPhase(bean);
// 3.2 拿到寄存该阶段值的 LifecycleGroup
LifecycleGroup group = phases.get(phase);
if (group == null) {
// 3.3 如果该阶段值的 LifecycleGroup 为 null,则新建一个
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
// 3.4 将 bean 增加到该 LifecycleGroup
group.add(beanName, bean);
}
});
// 4. 如果 phases 不为空
if (!phases.isEmpty()) {List<Integer> keys = new ArrayList<>(phases.keySet());
// 4.1 按阶段值进行排序
Collections.sort(keys);
// 4.2 按阶段值程序,调用 LifecycleGroup 中的所有 Lifecycle 的 start 办法
for (Integer key : keys) {phases.get(key).start();}
}
}
3. 推送上下文刷新结束事件到相应的监听器
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
// 1. 如有必要,将事件装璜为 ApplicationEvent
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {applicationEvent = (ApplicationEvent) event;
}
else {applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 2. 应用事件播送器播送事件到相应的监听器
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
// 3. 同样的,通过 parent 公布事件.....
if (this.parent != null) {if (this.parent instanceof AbstractApplicationContext) {((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {this.parent.publishEvent(event);
}
}
}
这外面调用的 publishEvent 办法,和咱们自定义的监听器调用的 publishEvent 是同一个办法,ContextRefreshedEvent 是 Spirng 的一个事件称为上下文刷新结束事件,如果咱们在上下文刷新实现后要写一个公布事件,实现 ApplicationListener<ContextRefreshedEvent> 接口即可。
咱们在此举一个简略的例子。
这样,当 Spring 执行到 finishRefresh 办法时,就会将 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。
读者能够联合自定义事件比照一个和 Spring 提供的刷新上下文事件的区别,以便于更好的了解 Spring 的事件监听机制。
跟 ContextRefreshedEvent 类似的还有:ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent。
好啦,Spirng 的 refresh 办法到这里就完结啦,一共是九篇博客,实际上这也是 Spirng 的 IOC 的全部内容了,如果读者能把九篇的齐全消化,那么 spring 的 IOC 也就了解的七七八八了。