筆記簡述
本學習筆記主要介紹Spring的事件通知是如何實現的,以及源碼分析
Demo
事件定義
繼承 ApplicationEvent 類
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@Getter
public class EventDemo extends ApplicationEvent {
private String message;
// Object source 具體事件源類
public EventDemo(Object source, String message) {
super(source);
this.message = message;
}
}
事件監聽
實現 ApplicationListener 類,并重寫 onApplicationEvent() 方法
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class EventDemoListern implements ApplicationListener<EventDemo> {
@Override
public void onApplicationEvent(EventDemo event) {
System.out.println("收到信息: " + event.getMessage());
}
}
事件發布
ApplicationEventPublisher Bean 發布事件
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Component
public class EventDemoPublish {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public void publish(String message) {
EventDemo eventDemo = new EventDemo(this, message);
applicationEventPublisher.publishEvent(eventDemo);
}
}
源碼分析
事件是如何發送的?
從 demo 的代碼來看 事件是通過 ApplicationEventPublisher 類的 publishEvent() 方法發送的;那么通過斷點追蹤此方法的行為軌跡,我們會發現其實是調用了 AbstractApplicationContext 類的 publishEvent() 方法,那么請看下面的源碼
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
//判斷事件是否是 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 {
//發送事件的入口
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// 有父類也發送事件
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
既然找到了發送事件的入口,那么就先追蹤 applicationEventMulticaster() 方法
/** Helper class used in event publishing. */
@Nullable
private ApplicationEventMulticaster applicationEventMulticaster;
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
if (this.applicationEventMulticaster == null) {
throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
"call 'refresh' before multicasting events via the context: " + this);
}
return this.applicationEventMulticaster;
}
到這里我們只掌握了 ApplicationEventMulticaster 是個接口類,并不知道真正的實現類,而且也沒發現關于此接口的構造函數(稍后再揭秘實現類究竟是怎么來的);但是通過斷點追蹤 multicastEvent() 方法,不難發現其實是調用了 SimpleApplicationEventMulticaster 類的 multicastEvent(),源碼如下
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// getApplicationListeners() 獲取 event 對應的監聽者
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
// 調用實例
invokeListener(listener, event);
}
}
}
走到這里我們會發現事件的監聽者都來自 getApplicationListeners(event, type);
通知監聽者的其實是 invokeListener(listener, event);
揭秘如何獲取事件對應的監聽者
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Quick check for existing entry on ConcurrentHashMap...
// 內部維護的緩存 (ConcurrentHashMap) 方便下次獲取對應的監聽者
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
// Fully synchronized building and caching of a ListenerRetriever
synchronized (this.retrievalMutex) {
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
retriever = new ListenerRetriever(true);
//第一次獲取事件對應的監聽者并放置緩存
Collection<ApplicationListener<?>> listeners =
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// No ListenerRetriever caching -> no synchronization necessary
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
// 只截取了核心代碼
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.retrievalMutex) {
// 獲取所有 ApplicationListener 的實現類
// 注: listeners 和 listenerBeans 均是取內部類 ListenerRetriever 維護的 LinkedHashSet
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
for (ApplicationListener<?> listener : listeners) {
// 判斷 listener 的 event 是否一致
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
...
return allListeners;
}
// 內部類
private class ListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
private final boolean preFiltered;
public ListenerRetriever(boolean preFiltered) {
this.preFiltered = preFiltered;
}
public Collection<ApplicationListener<?>> getApplicationListeners() {
...
}
}
這里同樣也會產生一個問題。我們知道 listeners 取自內部類 ListenerRetriever 維護的 applicationListeners 對象,那么 applicationListeners 何時 add 了呢?稍后再揭秘。
總結
獲取所有 ApplicationListener 的實現類后,依次判斷是否支持給定的事件,也就是事件的類型是否一致;最終通過特定的 cachKey 放置緩存
揭秘如何通知事件的監聽者
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 直接調用 onApplicationEvent
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
...
}
}
核心代碼:listener.onApplicationEvent(event);
拿到監聽者的實例,直接調用 onApplicationEvent() 方法
為了揭秘上面兩個問題,我們繼續觀察 AbstractApplicationContext 類,這個類里有我們想要的答案;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
Assert.notNull(listener, "ApplicationListener must not be null");
if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.addApplicationListener(listener);
}
this.applicationListeners.add(listener);
}
/**
* Return the list of statically specified ApplicationListeners.
*/
public Collection<ApplicationListener<?>> getApplicationListeners() {
return this.applicationListeners;
}
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
try {
...
// Initialize event multicaster for this context.
// 初始化 ApplicationEventMulticaster
// Initialize the ApplicationEventMulticaster.
// Uses SimpleApplicationEventMulticaster if none defined in the 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.
// 自己實現的 ApplicationListener 從這里實例化,經過復雜的 bean 實例過程,
// 最終由 ApplicationListenerDetector 類調用 addApplicationListener();
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
...
}