最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中的EventListenerMethodProcessor組件詳解

 更新時間:2023年12月25日 10:02:52   作者:安迪源文  
這篇文章主要介紹了Spring中的EventListenerMethodProcessor組件詳解,EventListenerMethodProcessor 是 Spring 事件機制中非常重要的一個組件,它管理了一組EventListenerFactory組件,用來將應用中每個使用@EventListener注解定義的事件監(jiān)聽,需要的朋友可以參考下

EventListenerMethodProcessor組件

1. 概述

EventListenerMethodProcessor 是 Spring 事件機制中非常重要的一個組件。它管理了一組EventListenerFactory組件,用來將應用中每個使用@EventListener注解定義的事件監(jiān)聽方法變成一個ApplicationListener實例注冊到容器。換句話講,框架開發(fā)者,或者應用開發(fā)者使用注解@EventListener定義的事件處理方法,如果沒有EventListenerMethodProcessor的發(fā)現(xiàn)和注冊,是不會被容器看到和使用的。

EventListenerMethodProcessor實現(xiàn)了如下三個接口 :

  • ApplicationContextAware
  • BeanFactoryPostProcessor
  • SmartInitializingSingleton

通過實現(xiàn)接口ApplicationContextAware,容器會將當前應用上下文ApplicationContext告訴EventListenerMethodProcessor,這是EventListenerMethodProcessor用于檢測發(fā)現(xiàn)@EventListener注解方法的來源,生成的ApplicationListener也放到該應用上下文。

通過實現(xiàn)接口BeanFactoryPostProcessor,EventListenerMethodProcessor變成了一個BeanFactory的后置處理器,也就是說,在容器啟動過程中的后置處理階段,啟動過程會調用EventListenerMethodProcessor的方法postProcessBeanFactory。在這個方法中,EventListenerMethodProcessor會找到容器中所有類型為EventListenerFactory的bean,最終@EventListener注解方法的檢測發(fā)現(xiàn),以及ApplicationListener實例的生成和注冊,靠的是這些EventListenerFactory組件。

而通過實現(xiàn)接口SmartInitializingSingleton,在容器啟動過程中所有單例bean創(chuàng)建階段(此階段完成前,這些bean并不會供外部使用)的末尾,EventListenerMethodProcessor的方法afterSingletonsInstantiated會被調用。在這里,EventListenerMethodProcessor會便利容器中所有的bean,進行@EventListener注解方法的檢測發(fā)現(xiàn),以及ApplicationListener實例的生成和注冊。

2. 源代碼

代碼版本 : Spring Context 5.2.0.RELEASE

package org.springframework.context.event;
//... 省略 import
/**
 * Registers {@link EventListener} methods as individual {@link ApplicationListener} instances.
 * Implements {@link BeanFactoryPostProcessor} (as of 5.1) primarily for early retrieval,
 * avoiding AOP checks for this processor bean and its {@link EventListenerFactory} delegates.
 *
 * @author Stephane Nicoll
 * @author Juergen Hoeller
 * @since 4.2
 * @see EventListenerFactory
 * @see DefaultEventListenerFactory
 */
public class EventListenerMethodProcessor
		implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {
	protected final Log logger = LogFactory.getLog(getClass());
    // 用于記錄檢測發(fā)現(xiàn)`@EventListener`注解方法,生成和注冊`ApplicationListener`實例的應用上下文
	@Nullable
	private ConfigurableApplicationContext applicationContext;
   // 記錄當前 BeanFactory, 實際上這個變量可用可不用,因為通過 applicationContext 也可以找到
   // 當前 BeanFactory
	@Nullable
	private ConfigurableListableBeanFactory beanFactory;
   // 記錄從容器中找到的所有 EventListenerFactory
	@Nullable
	private List<EventListenerFactory> eventListenerFactories;
	private final EventExpressionEvaluator evaluator = new EventExpressionEvaluator();
    // 緩存機制,記住那些根本任何方法上沒有使用注解 @EventListener 的類,避免處理過程中二次處理 
	private final Set<Class<?>> nonAnnotatedClasses = Collections.newSetFromMap(new ConcurrentHashMap<>(64));
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext,
				"ApplicationContext does not implement ConfigurableApplicationContext");
		this.applicationContext = (ConfigurableApplicationContext) applicationContext;
	}
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
       // 從容器中找到所有的  EventListenerFactory 組件
       // 常見的一些 EventListenerFactory :
       // TransactionalEventListenerFactory --
       // 用于支持使用 @TransactionalEventListener 注解的事件監(jiān)聽器, @TransactionalEventListener 是一種特殊的
       // @EventListener,它定義的事件監(jiān)聽器應用于事務提交或者回滾的某些特殊時機,
       // 由 ProxyTransactionManagementConfiguration 注冊到容器
       // 注冊到容器
       // DefaultEventListenerFactory -- 系統(tǒng)缺省, 最低優(yōu)先級,如果其他 EventListenerFactory 都不支持的時候使用
		Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
		List<EventListenerFactory> factories = new ArrayList<>(beans.values());
		AnnotationAwareOrderComparator.sort(factories);
		this.eventListenerFactories = factories;
	}
	@Override
	public void afterSingletonsInstantiated() {
		ConfigurableListableBeanFactory beanFactory = this.beanFactory;
		Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
       // 這里獲取容器中所有bean組件的名稱, 
		String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
		for (String beanName : beanNames) {
          // 遍歷每個bean組件,檢測其中`@EventListener`注解方法,生成和注冊`ApplicationListener`實例
			if (!ScopedProxyUtils.isScopedTarget(beanName)) {
				Class<?> type = null;
				try {
					type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
				}
				catch (Throwable ex) {
					// An unresolvable bean type, probably from a lazy bean - let's ignore it.
					if (logger.isDebugEnabled()) {
						logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
					}
				}
				if (type != null) {
					if (ScopedObject.class.isAssignableFrom(type)) {
						try {
							Class<?> targetClass = AutoProxyUtils.determineTargetClass(
									beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
							if (targetClass != null) {
								type = targetClass;
							}
						}
						catch (Throwable ex) {
							// An invalid scoped proxy arrangement - let's ignore it.
							if (logger.isDebugEnabled()) {
								logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
							}
						}
					}
					try {
                     // 注意這一行,針對一個bean的真正的`@EventListener`注解方法檢測,
                     // `ApplicationListener`實例生成注冊發(fā)生在這里
						processBean(beanName, type);
					}
					catch (Throwable ex) {
						throw new BeanInitializationException("Failed to process @EventListener " +
								"annotation on bean with name '" + beanName + "'", ex);
					}
				}
			}
		}
	}
   // 該方法拿到某個bean的名稱和它的目標類,在這個范圍上檢測`@EventListener`注解方法,
   // 生成和注冊`ApplicationListener`實例
	private void processBean(final String beanName, final Class<?> targetType) {
		if (!this.nonAnnotatedClasses.contains(targetType) &&
				AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
				!isSpringContainerClass(targetType)) {
			Map<Method, EventListener> annotatedMethods = null;
			try {
             // *** 注意這里, 這里檢測當前類targetType上使用了注解 @EventListener 的方法
				annotatedMethods = MethodIntrospector.selectMethods(targetType,
						(MethodIntrospector.MetadataLookup<EventListener>) method ->
								AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
			}
			catch (Throwable ex) {
				// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
				if (logger.isDebugEnabled()) {
					logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
				}
			}
			if (CollectionUtils.isEmpty(annotatedMethods)) {
              // 如果當前類 targetType 中沒有任何使用了 注解 @EventListener 的方法,則將該類保存到
              // 緩存 nonAnnotatedClasses, 從而避免當前處理方法重入該類,其目的應該是為了提高效率,             
				this.nonAnnotatedClasses.add(targetType);
				if (logger.isTraceEnabled()) {
					logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
				}
			}
			else {
              // 發(fā)現(xiàn)當前類 targetType 中有些方法使用了注解 @EventListener,現(xiàn)在根據這些方法上的信息
              // 對應地創(chuàng)建和注冊ApplicationListener實例
				// Non-empty set of methods
				ConfigurableApplicationContext context = this.applicationContext;
				Assert.state(context != null, "No ApplicationContext set");
              // 注意,這里使用到了  this.eventListenerFactories, 這些 EventListenerFactory 是在 
              // 該類 postProcessBeanFactory 方法調用時被記錄的
				List<EventListenerFactory> factories = this.eventListenerFactories;
				Assert.state(factories != null, "EventListenerFactory List not initialized");
				for (Method method : annotatedMethods.keySet()) {
					for (EventListenerFactory factory : factories) {
						if (factory.supportsMethod(method)) {
                        // 如果當前 EventListenerFactory factory 支持處理該 @EventListener 注解的方法,
                        // 則使用它創(chuàng)建 ApplicationListener
							Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
							ApplicationListener<?> applicationListener =
									factory.createApplicationListener(beanName, targetType, methodToUse);
							if (applicationListener instanceof ApplicationListenerMethodAdapter) {
								((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
							}
                        // 將所生成的  ApplicationListener 實例注冊到容器   
							context.addApplicationListener(applicationListener);
							break;
						}
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
							beanName + "': " + annotatedMethods);
				}
			}
		}
	}
	/**
	 * Determine whether the given class is an {@code org.springframework}
	 * bean class that is not annotated as a user or test {@link Component}...
	 * which indicates that there is no {@link EventListener} to be found there.
	 * @since 5.1
	 */
	private static boolean isSpringContainerClass(Class<?> clazz) {
		return (clazz.getName().startsWith("org.springframework.") &&
				!AnnotatedElementUtils.isAnnotated(ClassUtils.getUserClass(clazz), Component.class));
	}
}

到此這篇關于Spring中的EventListenerMethodProcessor組件詳解的文章就介紹到這了,更多相關EventListenerMethodProcessor組件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java中for循環(huán)遍歷刪除操作方法

    Java中for循環(huán)遍歷刪除操作方法

    在Java中,有些場景需要遍歷集合中的元素,然后根據條件進行刪除元素的操作,本文結合示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-11-11
  • Java實現(xiàn)隨機出題,10道10以內加減法計算代碼實例

    Java實現(xiàn)隨機出題,10道10以內加減法計算代碼實例

    這篇文章主要介紹了Java實現(xiàn)隨機出題,10道10以內加減法計算,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • Resilience4J通過yml設置circuitBreaker的方法

    Resilience4J通過yml設置circuitBreaker的方法

    Resilience4j是一個輕量級、易于使用的容錯庫,其靈感來自Netflix Hystrix,但專為Java 8和函數(shù)式編程設計,這篇文章主要介紹了Resilience4J通過yml設置circuitBreaker的方法,需要的朋友可以參考下
    2022-10-10
  • Spring中的@Scheduled源碼解析

    Spring中的@Scheduled源碼解析

    這篇文章主要介紹了Spring中的@Scheduled源碼解析,定時任務調度的基礎是ScheduledAnnotationBeanPostProcessor類,這是一個實現(xiàn)了BeanPostProcessor接口的后置處理器,需要的朋友可以參考下
    2023-09-09
  • 詳解MybatisPlus集成nacos導致druid連接不上數(shù)據庫

    詳解MybatisPlus集成nacos導致druid連接不上數(shù)據庫

    這篇文章主要介紹了詳解MybatisPlus集成nacos導致druid連接不上數(shù)據庫,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • Java業(yè)務校驗工具實現(xiàn)方法

    Java業(yè)務校驗工具實現(xiàn)方法

    這篇文章主要介紹了Java業(yè)務校驗工具實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • Java中BeanUtils.copyProperties()詳解及應用場景

    Java中BeanUtils.copyProperties()詳解及應用場景

    BeanUtils.copyProperties()是Apache?Commons?BeanUtils提供的方法,用于Java對象間屬性的復制,特別適用于DTO、VO和Entity之間的數(shù)據傳遞,這篇文章主要介紹了Java中BeanUtils.copyProperties()詳解及應用場景的相關資料,需要的朋友可以參考下
    2024-09-09
  • springboot中如何引入AOP切面編程

    springboot中如何引入AOP切面編程

    這篇文章主要介紹了springboot中如何引入AOP切面編程問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java直接調用本地大模型文件實現(xiàn)對話機器人

    Java直接調用本地大模型文件實現(xiàn)對話機器人

    這篇文章主要為大家詳細介紹了Java直接調用本地大模型文件實現(xiàn)對話機器人的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下
    2026-05-05
  • Spring中如何獲取request的方法匯總及其線程安全性分析

    Spring中如何獲取request的方法匯總及其線程安全性分析

    這篇文章主要給大家介紹了關于Spring中如何獲取request的方法匯總及其線程安全性分析的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-04-04

最新評論

北碚区| 黔江区| 咸阳市| 千阳县| 绥宁县| 平顶山市| 兰坪| 芷江| 敦化市| 蒙阴县| 讷河市| 凉山| 阜平县| 察雅县| 临武县| 龙川县| 昭平县| 双鸭山市| 沙河市| 绥江县| 舟山市| 澄城县| 仙游县| 治多县| 句容市| 肃宁县| 宁陵县| 萨迦县| 无极县| 光泽县| 博客| 涡阳县| 东兴市| 兴山县| 武功县| 临西县| 哈尔滨市| 浑源县| 江西省| 泾源县| 常宁市|