使用Spring注解@EventListener實現(xiàn)監(jiān)聽原理
@EventListener使用方式
package com.cyl.listener; import org.springframework.context.ApplicationEvent; import org.springframework.context.PayloadApplicationEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @Component public class CylOrderSecListener { @EventListener public void listen(ApplicationEvent event) { System.out.println(event); } }
@EventListener實現(xiàn)原理
主要通過EventListenerMethodProcessor和DefaultEventListenerFactory這兩個類實現(xiàn)。
- EventListenerMethodProcessor的作用是識別所有使用eventListener注解的方法
- DefaultEventListenerFactory將EventListenerMethodProcessor識別出的方法封裝成為監(jiān)聽器類
以代碼new AnnotationConfigApplicationContext為入口調(diào)試代碼去講解EventListenerMethodProcessor和DefaultEventListenerFactory如何去生效的
package com.cyl; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Test { public static void main(String[] args) { // 創(chuàng)建一個Spring容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AppConfig.class); context.refresh(); } }
1.引入時機-獲取bean定義
EventListenerMethodProcessor和DefaultEventListenerFactory的bean定義信息在容器初始化最開始階段,DefaultListableBeanFactory實例化后,被注冊到DefaultListableBeanFactory的beanDefinitionMap中。
執(zhí)行new AnnotationConfigApplicationContext,會優(yōu)先執(zhí)行父類 GenericApplicationContex構(gòu)造方法,實例化一個bean工廠
GenericApplicationContext執(zhí)行完后,會實例化AnnotatedBeanDefinitionReader,可以理解為容器內(nèi)一個bean定義閱讀器,負(fù)責(zé)將bean定義注冊到bean工廠中。
實例化AnnotatedBeanDefinitionReader會注冊一些bean定義到bean工廠中,其中就包括了EventListenerMethodProcessor和DefaultEventListenerFactory。
2.實例化時機-new對象
只引入了bean定義,還未真正對bean進(jìn)行實例化,實例化步驟是在spring執(zhí)行refresh時
走到方法內(nèi),會調(diào)用
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
關(guān)注代碼184行,獲取普通BeanFactoryPostProcessor類,而EventListenerMethodProcessor實現(xiàn)了BeanFactoryPostProcessor,此處打斷點也會獲取該類名
由于EventListenerMethodProcessor沒有實現(xiàn)PriorityOrdered或者Ordered接口,所以就被放入了nonOrderedPostProcessorNames中最后被執(zhí)行
當(dāng)執(zhí)行beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)會進(jìn)行實例化走到EventListenerMethodProcessor的構(gòu)造函數(shù)中
到此EventListenerMethodProcessor實例化好了,代碼繼續(xù)執(zhí)行
會執(zhí)行到EventListenerMethodProcessor.postProcessBeanFactory(),在這里實例化DefaultEventListenerFactory
3.作用時機->將加了EventListener注解的方法識別出來
并封裝為監(jiān)聽器,加載spring容器中
當(dāng)執(zhí)行
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
初始化后,
因EventListenerMethodProcessor實現(xiàn)了SmartInitializingSingleton,
而所有實現(xiàn)SmartInitializingSingleton類對象都需要在所有對象初始化后再執(zhí)行afterSingletonsInstantiated
即:
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
@Override public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { // 獲取合并后的BeanDefinition RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { // 獲取FactoryBean對象 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { // 創(chuàng)建真正的Bean對象(getObject()返回的對象) getBean(beanName); } } } else { // 創(chuàng)建Bean對象 getBean(beanName); } } } // 所有的非懶加載單例Bean都創(chuàng)建完了后 // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize") .tag("beanName", beanName); SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } smartInitialize.end(); } } }
當(dāng)執(zhí)行smartSingleton.afterSingletonsInstantiated();就會調(diào)到
org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated
EventListenerMethodProcessor真正的處理邏輯來了,主要看第38行關(guān)鍵方法
@Override public void afterSingletonsInstantiated() { ConfigurableListableBeanFactory beanFactory = this.beanFactory; Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set"); String[] beanNames = beanFactory.getBeanNamesForType(Object.class); for (String beanName : beanNames) { if (!ScopedProxyUtils.isScopedTarget(beanName)) { // 拿到當(dāng)前Bean對象的類型 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 { //關(guān)鍵方法 processBean(beanName, type); } catch (Throwable ex) { throw new BeanInitializationException("Failed to process @EventListener " + "annotation on bean with name '" + beanName + "'", ex); } } } } }
org.springframework.context.event.EventListenerMethodProcessor#processBean,關(guān)注下面代碼的注釋,主要邏輯就是會遍歷所有單例池中的對象,找到對象中加@EventListener注解的方法,然后通過EventListenerFactory將方法設(shè)置成監(jiān)聽器,注冊到spring容器中
private void processBean(final String beanName, final Class<?> targetType) { if (!this.nonAnnotatedClasses.contains(targetType) && AnnotationUtils.isCandidateClass(targetType, EventListener.class) && !isSpringContainerClass(targetType)) { // 找到所有加了@EventListener注解的方法 Map<Method, EventListener> annotatedMethods = null; try { 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)) { this.nonAnnotatedClasses.add(targetType); if (logger.isTraceEnabled()) { logger.trace("No @EventListener annotations found on bean class: " + targetType.getName()); } } else { // Non-empty set of methods ConfigurableApplicationContext context = this.applicationContext; Assert.state(context != null, "No ApplicationContext set"); List<EventListenerFactory> factories = this.eventListenerFactories; Assert.state(factories != null, "EventListenerFactory List not initialized"); for (Method method : annotatedMethods.keySet()) { for (EventListenerFactory factory : factories) { // 利用EventListenerFactory來對加了@EventListener注解的方法生成ApplicationListener對象 if (factory.supportsMethod(method)) { 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); } context.addApplicationListener(applicationListener); break; } } } if (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" + beanName + "': " + annotatedMethods); } } } }
發(fā)布事件,生效
容器初始化后,設(shè)置的監(jiān)聽器會收到容器初始化完成的事件,然后執(zhí)行自定義的監(jiān)聽事件
容器初始化最后階段,即執(zhí)行org.springframework.context.support.AbstractApplicationContext#finishRefresh
最終效果圖為:
總結(jié)
EventListenerMethodProcessor和DefaultEventListenerFactory兩個類是注解EventListener的邏輯處理類,先在spring容器初始化階段先顯示引入這兩個類的bean定義,然后spring容器在執(zhí)行beanFactory的后置處理器邏輯時,對這兩個類進(jìn)行實例化;
最后待所有非懶加載單例bean都初始化完后,執(zhí)行EventListenerMethodProcessor的afterSingletonsInstantiated即初始化后方法,識別出所有加了注解EventListener的方法,將這些方法用DefaultEventListenerFactory封裝成監(jiān)聽器類,注冊到spring容器中。
待發(fā)布事件時,再從spring容器中獲取所有監(jiān)聽器類,回調(diào)監(jiān)聽方法。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Fluent Mybatis零xml配置實現(xiàn)復(fù)雜嵌套查詢
本文主要介紹了Fluent Mybatis零xml配置實現(xiàn)復(fù)雜嵌套查詢,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08用StopWatch優(yōu)雅替代currentTimeMillis計算程序執(zhí)行耗時
別再用System.currentTimeMillis()計算程序執(zhí)行耗時了,擁抱StopWatch優(yōu)雅來優(yōu)雅的計算,代碼更簡潔效率更高,本文帶你了解StopWatch的使用2021-09-09Java實現(xiàn)Fast DFS、服務(wù)器、OSS上傳功能
這篇文章主要介紹了Java實現(xiàn)Fast DFS、服務(wù)器、OSS上傳功能,在實際的業(yè)務(wù)中,可以根據(jù)客戶的需求設(shè)置不同的文件上傳需求,支持普通服務(wù)器上傳+分布式上傳(Fast DFS)+云服務(wù)上傳OSS(OSS),需要的朋友可以參考下2024-04-04