Spring ApplicationContext(八)事件監聽機制
阿新 • • 發佈:2019-02-23
一個 ace end oid 其它 get throws 規範 bstr
Spring ApplicationContext(八)事件監聽機制
本節則重點關註的是 Spring 的事件監聽機制,主要是第 8 步:多播器註冊;第 10 步:事件註冊。
public void refresh() throws BeansException, IllegalStateException { // 8. 註冊多播器,事件監聽器的管理者 initApplicationEventMulticaster(); // 9. 專門留給子類初始化其它 bean 用,這是一個空的方法 onRefresh(); // 10. 註冊監聽器 registerListeners(); }
事件定義如下,實現了 JDK 的規範 EventListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
// 監聽 event 事件
void onApplicationEvent(E event);
}
一、ApplicationListener 實戰
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class MyApplicationListener implements ApplicationListener<ApplicationEvent> { @Override public void onApplicationEvent(ApplicationEvent event) { System.out.println("接收的事件:" + event); } }
運行後結果如下:
接收的事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.support.ClassPathXmlApplicationContext@16eabae: startup date [Sun Jul 29 12:41:42 CST 2018]; root of context hierarchy]
二、ApplicationEventMulticaster 多播器的初始化
ApplicationContext 中 refresh() 第 8 步 initApplicationEventMulticaster() 進行多播器的初始化工作
源代碼【AbstractApplicationContext】
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
三、ApplicationListener 註冊
ApplicationContext 中 refresh() 第 10 步 registerListeners() 進行事件監聽者的註冊工作。
源代碼【AbstractApplicationContext】
protected void registerListeners() {
// 1. 註冊靜態指定的偵聽器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 2. 註冊 ApplicationListener
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 3. Publish early application events
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
四、ApplicationEvent 事件發布
源代碼【AbstractApplicationContext】
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// 1. 如果 event 不是 ApplicationEvent,則需要進行封裝成 PayloadApplicationEvent
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
}
}
// 2. 發布事件 event,如果多播器懶加載,還沒有初始化則將該事件先放到 earlyApplicationEvents 容器中
// 等待多播器創建好了再發布事件 ???
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// 3. 父容器中也需要發布該事件 event
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
每天用心記錄一點點。內容也許不重要,但習慣很重要!
Spring ApplicationContext(八)事件監聽機制