您好,登錄后才能下訂單哦!
本篇內容介紹了“Springboot中AbstractApplicationEventMulticaster有什么作用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
Springboot的版本2.0.9.release,對應的SpringFramework值5.0.x.release。
AbstractApplicationEventMulticaster并不是Springboot里面的,而是屬于SpringFramework的。
圖1
如上圖1所示,AbstractApplicationEventMulticaster繼承了BeanFactoryAware,用于獲取BeanFactory;ApplicationEventMulticaster則包含增加、刪除ApplicationListener的接口方法,支持對象和String類型的bean名稱。
一開始以為AbstractApplicationEventMulticaster應該有個List<ApplicationListener>的屬性用于存放加入其中的ApplicationListener,但是看了源碼之后,發現Spring考慮的更周全、考慮的情況更多。
List-1
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware { private final AbstractApplicationEventMulticaster.ListenerRetriever defaultRetriever = new AbstractApplicationEventMulticaster.ListenerRetriever(false); final Map<AbstractApplicationEventMulticaster.ListenerCacheKey, AbstractApplicationEventMulticaster.ListenerRetriever> retrieverCache = new ConcurrentHashMap(64); @Nullable private ClassLoader beanClassLoader; @Nullable private BeanFactory beanFactory; private Object retrievalMutex; ... 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; } ...
如上的List-1,ListenerRetriever中的LinkedHashSet,才是真正存放ApplicationListener的地方。而retrieverCache則是用于作為緩存,為什么要做緩存,是因為我們丟給AbstractApplicationEventMulticaster的Event不一定會被發送,只有找到能支持這種Event的ApplicationListener才會進行發送。
首先來看下addApplicationListener,如下List-2,如果是ApplicationListener的實例,則加入到defaultRetriever的Set中,如果是String類型的beanName,則加入到defaultRetriever的applicationListenerBeans中,最后都調用retrieverCache的clear方法,retrieverCache是個線程安全的Map,因為新加入了ApplicationListener,所以我們需要更新我們的緩存。
List-2
public void addApplicationListener(ApplicationListener<?> listener) { synchronized(this.retrievalMutex) { Object singletonTarget = AopProxyUtils.getSingletonTarget(listener); if (singletonTarget instanceof ApplicationListener) { this.defaultRetriever.applicationListeners.remove(singletonTarget); } this.defaultRetriever.applicationListeners.add(listener); this.retrieverCache.clear(); } } public void addApplicationListenerBean(String listenerBeanName) { synchronized(this.retrievalMutex) { this.defaultRetriever.applicationListenerBeans.add(listenerBeanName); this.retrieverCache.clear(); } } ...
來看retrieveApplicationListeners方法的實現,這個很重要,因為發送Event之前,會先檢索出支持這種event的ApplicationListener。如下所示List-3:
遍歷applicationListeners,調用supportsEvent方法,如果支持,加將當前的ApplicationListener加入到結果集中。
之后遍歷applicationListenerBeans,先從BeanFactory中獲取對應的ApplicationListener實例,如果BeanFactory中含有對應的ApplicationListener,且supportsEvent方法返回true,那么將當前的ApplicationListener加入到結果集中。
最后調用AnnotationAwareOrderComparator進行排序。
List-3
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.ListenerRetriever retriever) { List<ApplicationListener<?>> allListeners = new ArrayList(); LinkedHashSet listeners; LinkedHashSet listenerBeans; synchronized(this.retrievalMutex) { listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans); } Iterator var7 = listeners.iterator(); while(var7.hasNext()) { ApplicationListener<?> listener = (ApplicationListener)var7.next(); if (this.supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListeners.add(listener); } allListeners.add(listener); } } if (!listenerBeans.isEmpty()) { BeanFactory beanFactory = this.getBeanFactory(); Iterator var15 = listenerBeans.iterator(); while(var15.hasNext()) { String listenerBeanName = (String)var15.next(); try { Class<?> listenerType = beanFactory.getType(listenerBeanName); if (listenerType == null || this.supportsEvent(listenerType, eventType)) { ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class); if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListenerBeans.add(listenerBeanName); } allListeners.add(listener); } } } catch (NoSuchBeanDefinitionException var13) { } } } AnnotationAwareOrderComparator.sort(allListeners); return allListeners; }
AbstractApplicationEventMulticaster的子類,需要實現multicastEvent方法,我們來看下SimpleApplicationEventMulticaster是如何實現的。
如下List-4所示,默認情況下taskExecutor是null。
multicastEvent方法中調用父類的getApplicationListeners方法獲取支持Event的ApplicationListener,之后遍歷ApplicationListener,如果taskExecutor不是null,則交給Executor;否則逐個調用ApplicationListener的onApplicationEvent方法。
List-4
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { @Nullable private Executor taskExecutor; public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event); Iterator var4 = this.getApplicationListeners(event, type).iterator(); while(var4.hasNext()) { ApplicationListener<?> listener = (ApplicationListener)var4.next(); Executor executor = this.getTaskExecutor(); if (executor != null) { executor.execute(() -> { this.invokeListener(listener, event); }); } else { this.invokeListener(listener, event); } } } private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { listener.onApplicationEvent(event); } catch (ClassCastException var6) { String msg = var6.getMessage(); if (msg != null && !this.matchesClassCastMessage(msg, event.getClass())) { throw var6; } } } ...
Springboot中SpringApplicationRunListener的默認實現有個EventPublishingRunListener,如下List-5所示
List-5
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SimpleApplicationEventMulticaster initialMulticaster; ... @Override public void starting() { this.initialMulticaster.multicastEvent( new ApplicationStartingEvent(this.application, this.args)); } @Override public void environmentPrepared(ConfigurableEnvironment environment) { this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent( this.application, this.args, environment)); } ... @Override public void started(ConfigurableApplicationContext context) { context.publishEvent( new ApplicationStartedEvent(this.application, this.args, context)); } ...
如List-5中所示,Springboot啟動的不同階段,會傳不同的event實現給EventPublishingRunListener,而EventPublishingRunListener則用Delete委托模式,交給initialMulticaster去處理。當然,started、running、failed事件則交給ConfigurableApplicationContext去處理。
來看EventPublishingRunListener的構造方法如下List-6所示,從SpringApplication中獲取Listener,之后加入到SimpleApplicationEventMulticaster中,所以Springboot中的事件是先交給SpringApplicationRunListener,之后SpringApplicationRunListener再委托給ApplicationListener的實現類完成具體的。
List-6
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final SimpleApplicationEventMulticaster initialMulticaster; ... public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } } ...
ApplicationListener的實現類如下圖2
圖2
“Springboot中AbstractApplicationEventMulticaster有什么作用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。