Spring中的EventListenerMethodProcessor組件詳解
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的后置處理器,也就是說,在容器啟動過程中的后置處理階段,啟動過程會調(diào)用EventListenerMethodProcessor的方法postProcessBeanFactory。在這個方法中,EventListenerMethodProcessor會找到容器中所有類型為EventListenerFactory的bean,最終@EventListener注解方法的檢測發(fā)現(xiàn),以及ApplicationListener實例的生成和注冊,靠的是這些EventListenerFactory組件。
而通過實現(xiàn)接口SmartInitializingSingleton,在容器啟動過程中所有單例bean創(chuàng)建階段(此階段完成前,這些bean并不會供外部使用)的末尾,EventListenerMethodProcessor的方法afterSingletonsInstantiated會被調(diào)用。在這里,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)在根據(jù)這些方法上的信息 // 對應地創(chuàng)建和注冊ApplicationListener實例 // Non-empty set of methods ConfigurableApplicationContext context = this.applicationContext; Assert.state(context != null, "No ApplicationContext set"); // 注意,這里使用到了 this.eventListenerFactories, 這些 EventListenerFactory 是在 // 該類 postProcessBeanFactory 方法調(diào)用時被記錄的 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)); } }
到此這篇關(guān)于Spring中的EventListenerMethodProcessor組件詳解的文章就介紹到這了,更多相關(guān)EventListenerMethodProcessor組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實現(xiàn)1M圖片壓縮優(yōu)化到100kb實現(xiàn)示例
這篇文章主要為大家介紹了java實現(xiàn)1M圖片壓縮優(yōu)化到100kb示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07Spring?JPA?deleteInBatch導致StackOverflow問題
這篇文章主要介紹了Spring?JPA?deleteInBatch導致StackOverflow問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05SpringBoot?項目打成?jar后加載外部配置文件的操作方法
這篇文章主要介紹了SpringBoot?項目打成?jar后加載外部配置文件的操作方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03