欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring事件監(jiān)聽源碼解析流程分析

 更新時(shí)間:2023年08月21日 11:01:48   作者:CodAlun  
spring事件監(jiān)聽機(jī)制離不開容器IOC特性提供的支持,比如容器會(huì)自動(dòng)創(chuàng)建事件發(fā)布器,自動(dòng)識(shí)別用戶注冊(cè)的監(jiān)聽器并進(jìn)行管理,在特定的事件發(fā)布后會(huì)找到對(duì)應(yīng)的事件監(jiān)聽器并對(duì)其監(jiān)聽方法進(jìn)行回調(diào),這篇文章主要介紹了Spring事件監(jiān)聽源碼解析,需要的朋友可以參考下

spring事件監(jiān)聽機(jī)制離不開容器IOC特性提供的支持,比如容器會(huì)自動(dòng)創(chuàng)建事件發(fā)布器,自動(dòng)識(shí)別用戶注冊(cè)的監(jiān)聽器并進(jìn)行管理,在特定的事件發(fā)布后會(huì)找到對(duì)應(yīng)的事件監(jiān)聽器并對(duì)其監(jiān)聽方法進(jìn)行回調(diào)。Spring幫助用戶屏蔽了關(guān)于事件監(jiān)聽機(jī)制背后的很多細(xì)節(jié),使用戶可以專注于業(yè)務(wù)層面進(jìn)行自定義事件開發(fā)。然而我們對(duì)內(nèi)部的實(shí)現(xiàn)還是有一些疑問,比如

• 事件發(fā)布器ApplicationEventMulticaster是何時(shí)被初始化的,初始化過程中都做了什么?
• 注冊(cè)事件監(jiān)聽器的過程是怎樣的,容器怎么識(shí)別出它們并進(jìn)行管理?
• 容器發(fā)布事件的流程是怎樣的?它如何根據(jù)發(fā)布的事件找到對(duì)應(yīng)的事件監(jiān)聽器,事件和由該事件觸發(fā)的監(jiān)聽器之間的匹配規(guī)則是怎樣的?

初始化事件發(fā)布器流程

真正的事件發(fā)布器是ApplicationEventMulticaster,它定義在AbstractApplicationContext中,并在ApplicationContext容器啟動(dòng)的時(shí)候進(jìn)行初始化。在容器啟動(dòng)的refrsh()方法中可以找到初始化事件發(fā)布器的入口方法,如下圖所示:

/**
	 * Initialize the ApplicationEventMulticaster.
	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	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);
			if (logger.isTraceEnabled()) {
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			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() + "]");
			}
		}
	}

這里會(huì)根據(jù)核心容器beanFactory中是否有id為applicationEventMulticaster的bean分兩種情況

(1)容器中已有id為applicationEventMulticaster的bean:直接從容器緩存獲取或是創(chuàng)建該bean實(shí)例,并交由成員變量applicationEventMulticaster保存。當(dāng)用戶自定義了事件發(fā)布器并向容器注冊(cè)時(shí)會(huì)執(zhí)行該流程。
(2)容器中不存在applicationEventMulticaster的bean:這是容器默認(rèn)的執(zhí)行流程,會(huì)創(chuàng)建一個(gè)SimpleApplicationEventMulticaster,其僅在實(shí)現(xiàn)事件發(fā)布器基本功能(管理事件監(jiān)聽器以及發(fā)布容器事件)的前提下,增加了可以設(shè)置任務(wù)執(zhí)行器Executor和錯(cuò)誤處理器ErrorHandler的功能,當(dāng)設(shè)置Executor為線程池時(shí),則會(huì)以異步的方式對(duì)事件監(jiān)聽器進(jìn)行回調(diào),而ErrorHandler允許我們?cè)诨卣{(diào)方法執(zhí)行錯(cuò)誤時(shí)進(jìn)行自定義處理。默認(rèn)情況下,這兩個(gè)變量都為null。

之后會(huì)調(diào)用beanFactory.registerSingleton方法將創(chuàng)建的SimpleApplicationEventMulticaster實(shí)例注冊(cè)為容器的單實(shí)例bean。
初始化事件發(fā)布器總結(jié)一句話:由容器實(shí)例化用戶自定義的事件發(fā)布器或者由容器幫我們創(chuàng)建一個(gè)簡單的事件發(fā)布器并交由容器管理。

注冊(cè)事件監(jiān)聽器流程

注冊(cè)事件監(jiān)聽器的流程在初始化事件發(fā)布器之后,如下圖所示:

/**
	 * Add beans that implement ApplicationListener as listeners.
	 * Doesn't affect other listeners, which can be added without being beans.
	 */
	protected void registerListeners() {
		// 首先注冊(cè)靜態(tài)指定的監(jiān)聽器。
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}
		// 不要在這里初始化FactoryBeans:我們需要保留所有常規(guī)Bean
		// 未初始化以允許后處理器應(yīng)用于它們!
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}
		// 發(fā)布早期應(yīng)用程序事件
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

容器事件發(fā)布流程

org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, ResolvableType)

將給定事件發(fā)布給所有偵聽器

前面說,在啟動(dòng)的時(shí)候如果沒有一個(gè)beanName叫做applicationEventMulticaster的ApplicationEventMulticaster,那使用的就是SimpleApplicationEventMulticaster,該組件會(huì)在容器啟動(dòng)時(shí)被自動(dòng)創(chuàng)建,并以單例的形式存在,管理了所有的事件監(jiān)聽器,并提供針對(duì)所有容器內(nèi)事件的發(fā)布功能。

org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)

@Override 
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { 
	//獲取事件類型 
	ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); 
	//獲取事件發(fā)布器內(nèi)的任務(wù)執(zhí)行器,默認(rèn)該方法返回null 
	Executor executor = getTaskExecutor(); 
	//遍歷所有和事件匹配的事件監(jiān)聽器 
	for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { 
		if (executor != null) { 
			//異步回調(diào)監(jiān)聽方法 
			executor.execute(() -> invokeListener(listener, event)); 
		} else { 
			//同步回調(diào)監(jiān)聽方法 
			invokeListener(listener, event); 
		} 
	} 
}

如何根據(jù)事件類型找到匹配的所有事件監(jiān)聽器?

org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent, ResolvableType)

/**
	 * Return a Collection of ApplicationListeners matching the given
	 * event type. Non-matching listeners get excluded early.
	 * @param event the event to be propagated. Allows for excluding
	 * non-matching listeners early, based on cached matching information.
	 * @param eventType the event type
	 * @return a Collection of ApplicationListeners
	 * @see org.springframework.context.ApplicationListener
	 */
	protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {
                      // 獲取事件中的事件源對(duì)象
		Object source = event.getSource();
		// 獲取事件源類型
		Class<?> sourceType = (source != null ? source.getClass() : null);
		// 以事件類型和事件源類型為參數(shù)構(gòu)建一個(gè)cacheKey ,用于從緩存map中獲取與之匹配的監(jiān)聽器列表
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
		// 根據(jù)cacheKey從緩存中獲取CachedListenerRetriever
		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);
				// 不存在就檢索給定事件和源類型的應(yīng)用程序偵聽器,并放到緩存
				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);
		}
	}

如果事件時(shí)第一次發(fā)布,會(huì)遍歷所有的事件監(jiān)聽器,并根據(jù)事件類型和事件源類型進(jìn)行匹配:

org.springframework.context.event.AbstractApplicationEventMulticaster#retrieveApplicationListeners

/**
	 * Actually retrieve the application listeners for the given event and source type.
	 * @param eventType the event type
	 * @param sourceType the event source type
	 * @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
	 * @return the pre-filtered list of application listeners for the given event and source type
	 */
	private Collection<ApplicationListener<?>> retrieveApplicationListeners(
			ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {
                       // 存放監(jiān)聽器的列表
		List<ApplicationListener<?>> allListeners = new ArrayList<>();
		Set<ApplicationListener<?>> listeners;
		Set<String> listenerBeans;
		synchronized (this.retrievalMutex) {
			listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
			listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
		}
		// 添加以編程方式注冊(cè)的偵聽器,
		// 包括來自ApplicationListenerDetector的偵聽器(單例bean和內(nèi)部bean)。
		for (ApplicationListener<?> listener : listeners) {
			if (supportsEvent(listener, eventType, sourceType)) {
				if (retriever != null) {
					retriever.applicationListeners.add(listener);
				}
				allListeners.add(listener);
			}
		}
		// 按bean名稱添加偵聽器,這可能與上面通過編程注冊(cè)的偵聽器重疊,
		// 但這里可能有額外的元數(shù)據(jù)。
		if (!listenerBeans.isEmpty()) {
			ConfigurableBeanFactory beanFactory = getBeanFactory();
			for (String listenerBeanName : listenerBeans) {
				try {
					if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
						ApplicationListener<?> listener =
								beanFactory.getBean(listenerBeanName, ApplicationListener.class);
						if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
							if (retriever != null) {
								if (beanFactory.isSingleton(listenerBeanName)) {
									retriever.applicationListeners.add(listener);
								}
								else {
									retriever.applicationListenerBeans.add(listenerBeanName);
								}
							}
							allListeners.add(listener);
						}
					}
					else {
						// 刪除最初來自ApplicationListenerDetector的不匹配偵聽器,
						// 可能會(huì)被上面額外的BeanDefinition元數(shù)據(jù)(例如工廠方法泛型)排除。
						Object listener = beanFactory.getSingleton(listenerBeanName);
						if (retriever != null) {
							retriever.applicationListeners.remove(listener);
						}
						allListeners.remove(listener);
					}
				}
				catch (NoSuchBeanDefinitionException ex) {
					// 單一偵聽器實(shí)例(沒有支持bean定義)消失-可能在銷毀階段中期}
			}
		}
		//對(duì)匹配的監(jiān)聽器列表進(jìn)行排序
		AnnotationAwareOrderComparator.sort(allListeners);
		if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
			retriever.applicationListeners.clear();
			retriever.applicationListeners.addAll(allListeners);
		}
		return allListeners;
	}

容器事件發(fā)布的整個(gè)流程,可以總結(jié)如下

到此這篇關(guān)于Spring事件監(jiān)聽源碼解析的文章就介紹到這了,更多相關(guān)Spring事件監(jiān)聽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論