目錄
代碼塊1:initApplicationEventMulticaster
Spring IoC源碼學習全系列
Spring IoC源碼學習:ApplicationContext 刷新前的配置
Spring IoC源碼學習:obtainFreshBeanFactory詳解
Spring IoC源碼學習:parseDefaultElement詳解
Spring IoC源碼學習:parseCustomElement詳解
Spring IoC源碼學習:obtainFreshBeanFactory詳解
Spring IoC源碼學習:invokeBeanFactoryPostProcessors詳解
Spring IoC源碼學習:registerBeanPostProcessors詳解
Spring IoC源碼學習:finishBeanFactoryInitialization詳解
Spring IoC源碼學習:createBean詳解(上)
Spring IoC源碼學習:createBean詳解(下)
Spring IoC源碼學習:finishRefresh 詳解
前言
Spring IoC 的核心內容已經介紹完畢,本文將對最後一個方法 finishRefresh 進行介紹。由於存在上下文關係,本文也會對 initApplicationEventMulticaster 方法、registerListeners 方法進行介紹。
正文
首先,我們回到 refresh 方法。
@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();
}
}
}
initApplicationEventMulticaster():初始化應用的事件廣播器,見代碼塊1詳解。
registerListeners():註冊監聽器,見代碼塊2詳解。
finishRefresh():完成上下文的刷新工作,見代碼塊3詳解。
代碼塊1:initApplicationEventMulticaster
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.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
// 1.2 如果不存在,則使用SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 並將SimpleApplicationEventMulticaster作爲默認的事件廣播器,註冊到BeanFactory中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
內容比較簡單,就是要初始化應用的事件廣播器。通過之前的學習我們知道,在 Spring 中,有一些內部的 bean 會使用固定的 beanName,這邊的事件廣播器就是這樣,固定使用 beanName :applicationEventMulticaster。
具體的,如果當前 BeanFactory 中已經存在 beanName = applicationEventMulticaster 的 bean 實例或者 BeanDefinition,那麼就使用該 bean 作爲 applicationEventMulticaster。
否則,新建一個默認的事件廣播器 SimpleApplicationEventMulticaster 作爲 applicationEventMulticaster,並且會註冊到 BeanFactory 中。
代碼塊2:registerListeners
protected void registerListeners() {
// Register statically specified listeners first.
// 1.通過硬編碼調用addApplicationListener方法添加的監聽器處理(可以通過自定義ApplicationContextInitializer添加)
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 2.通過配置文件或註解注入BeanFactory的監聽器處理
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 3.使用事件廣播器,發佈早期應用程序事件到相應的監聽器
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
1.通過硬編碼調用 addApplicationListener 方法添加的監聽器處理,可以通過自定義 ApplicationContextInitializer 添加,關於自定義 ApplicationContextInitializer 請見 Spring IoC:ApplicationContext 刷新前的配置 中的代碼塊12。
代碼塊3:finishRefresh
protected void finishRefresh() {
// 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.爲此上下文初始化生命週期處理器,見代碼塊4詳解。
2.首先將刷新完畢事件傳播到生命週期處理器,見代碼塊5詳解。
3.推送上下文刷新完畢事件到相應的監聽器,見代碼塊6詳解。
代碼塊4:initLifecycleProcessor
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 1.判斷BeanFactory是否已經存在生命週期處理器(固定使用beanName=lifecycleProcessor)
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
// 1.1 如果已經存在,則將該bean賦值給lifecycleProcessor
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isDebugEnabled()) {
logger.debug("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.isDebugEnabled()) {
logger.debug("Unable to locate LifecycleProcessor with name '" +
LIFECYCLE_PROCESSOR_BEAN_NAME +
"': using default [" + this.lifecycleProcessor + "]");
}
}
}
初始化生命週期處理器,過程同代碼塊1類似,優先使用用戶自定義的生命週期處理器;如果用戶沒有自定義,則使用默認的 DefaultLifecycleProcessor。
代碼塊5:onRefresh
@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
// 1.獲取所有的Lifecycle bean
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
// 將Lifecycle bean 按階段分組,階段通過實現Phased接口得到
Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
// 2.遍歷所有Lifecycle bean,按階段值分組
for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
Lifecycle bean = entry.getValue();
// 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(entry.getKey(), bean);
}
}
// 4.如果phases不爲空
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<Integer>(phases.keySet());
// 4.1 按階段值進行排序
Collections.sort(keys);
// 4.2 按階段值順序,調用LifecycleGroup中的所有Lifecycle的start方法
for (Integer key : keys) {
phases.get(key).start();
}
}
}
這邊講下 autoStartupOnly 這個參數。
autoStartupOnly = true 時,代表這次刷新是 ApplicationContext 刷新時容器自動啓動,在這個階段只會觸發 SmartLifecycle,並且要求 SmartLifecycle 的 isAutoStartup() 方法必須返回 true。
而 autoStartupOnly = false,代表這次刷新是通過顯示的調用啓動,會觸發所有的 Lifecycle。
這邊還引入了 Phased 接口,這個接口類似於 Ordered 接口,只有一個方法用於返回一個 “階段值”,範圍爲 Integer.MIN_VALUE ~ Integer.MAX_VALUE。在啓動過程,“階段值” 小的會被優先調用,而在關閉過程,“階段值” 大的會被優先調用。
代碼塊6:publishEvent
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
// 1.如有必要,將事件裝飾爲ApplicationEvent
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
applicationEvent = new PayloadApplicationEvent<Object>(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);
}
}
}
2.使用事件廣播器廣播事件到相應的監聽器,見代碼塊7詳解。
代碼塊7:multicastEvent
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 1.getApplicationListeners:返回與給定事件類型匹配的應用監聽器集合
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 2.返回此廣播器的當前任務執行程序
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
// 3.1 executor不爲null,則使用executor調用監聽器
invokeListener(listener, event);
}
});
} else {
// 3.2 否則,直接調用監聽器
invokeListener(listener, event);
}
}
}
3.2 調用監聽器,見代碼塊8詳解。
代碼塊8:invokeListener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
// 1.返回此廣播器的當前錯誤處理程序
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
// 2.1 如果errorHandler不爲null,則使用帶錯誤處理的方式調用給定的監聽器
doInvokeListener(listener, event);
} catch (Throwable err) {
errorHandler.handleError(err);
}
} else {
// 2.2 否則,直接調用調用給定的監聽器
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 觸發監聽器的onApplicationEvent方法,參數爲給定的事件
listener.onApplicationEvent(event);
} catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || msg.startsWith(event.getClass().getName())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
} else {
throw ex;
}
}
}
自定義監聽器實現
如果我們想在 Spring IoC 容器構建完畢之後進行一些邏輯,就可以通過監聽器來實現。
創建一個自定義監聽器,實現 ApplicationListener 接口,監聽 ContextRefreshedEvent(上下文刷新完畢事件),並且將該監聽器註冊到 Spring IoC 容器即可。
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
/**
* @author joonwhee
* @date 2019/6/22
*/
@Component
public class MyRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 自己的邏輯處理
}
}
這樣,當 Spring 執行到 finishRefresh 方法時,就會將 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。
跟 ContextRefreshedEvent 相似的還有:ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent,有興趣的可以自己看看這幾個事件的使用場景。
當然,我們也可以自定義監聽事件,只需要繼承 ApplicationContextEvent 抽象類即可。
總結
本文主要介紹了幾個用於擴展使用的功能:
- ApplicationEventMulticaster:應用事件廣播器,用於發佈事件到相應的監聽器。
- LifecycleProcessor:生命週期處理器,用於處理生命週期事件。
- Lifecycle:定義生命週期控制方法的接口,特別是 SmartLifecycle,可以在 Spring IoC 容器刷新完畢時進行觸發。
- ApplicationContextEvent:應用事件的基類。
- ApplicationListener,應用事件監聽器,用於監聽應用事件。