javascript
Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析
文章目錄
- Pre
- 概覽
- 開天辟地的時候初始化的處理器
- @EventListener
- EventListenerMethodProcessor
- afterSingletonsInstantiated
- 小結
- 發布事件
- 附 <異步派發和異常處理器>
Pre
Spring5源碼 - 10 Spring事件監聽機制_應用篇
Spring5源碼 - 11 Spring事件監聽機制_源碼篇
Spring5源碼 - 12 Spring事件監聽機制_異步事件監聽應用及源碼解析
通過上面三篇文章的學習,是不是發現沒有看到Spring是如何解析@EventListener注解的呢? Let’s go ~~~
概覽
Spring容器在啟動的時候初始化EventListenerMethodProcessor和DefaultEventListenerFactory,用于處理@EventListener注解, 調用EventListenerMethodProcessor的afterSingletonsInstantiated方法。
開天辟地的時候初始化的處理器
/*** 處理監聽方法的注解解析器EventListenerMethodProcessor*/if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}/*** 注冊事件監聽器工廠*/if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}一個是注冊一個用于解析@EventListener注解的EventListenerMethodProcessor ,一個是注冊事件監聽工廠。
@EventListener
EventListenerMethodProcessor
我們來看下EventListenerMethodProcessor的類繼承結構
EventListenerMethodProcessor 實現了 EventListenerMethodProcessor,所以執行 BeanFactory 后置處理器時,會調用 postProcessBeanFactory(),將 DefaultEventListenerFactory 添加到緩存中。
可以看到EventListenerMethodProcessor實現了SmartInitializingSingleton接口 , 那肯定要重寫 afterSingletonsInstantiated方法。
我們知道SmartInitializingSingleton接口是在所有的Bean實例化完成以后,Spring回調的方法。 獲取所有的 BeanFactory,找到其中標注了 @EventListener 的方法,利用反射和 DefaultEventListenerFactory 為其創建 ApplicationListener,并添加到事件派發器的緩存中。
refresh----> finishBeanFactoryInitialization(beanFactory);---->preInstantiateSingletons()
afterSingletonsInstantiated
我們看下 EventListenerMethodProcessor的afterSingletonsInstantiated方法
@Overridepublic void afterSingletonsInstantiated() {//從BeanFactory中獲取EventListenerFactory,EventListenerFactory共有2個實現,一個是DefaultEventListenerFactory,對普通的@EventListener進行解析,另一個是TransactionalEventListenerFactory,可以對@TransactionalEventListener進行解析。List<EventListenerFactory> factories = getEventListenerFactories();ConfigurableApplicationContext context = getApplicationContext();// 獲取所有的beanNamesString[] beanNames = context.getBeanNamesForType(Object.class);// 遍歷循環for (String beanName : beanNames) {........// 關鍵:處理bean processBean(factories, beanName, type);.........}}} protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {if (!this.nonAnnotatedClasses.contains(targetType)) {Map<Method, EventListener> annotatedMethods = null;try {//查找帶@EventListener注解的方法annotatedMethods = MethodIntrospector.selectMethods(targetType,new MethodIntrospector.MetadataLookup<EventListener>() {@Overridepublic EventListener inspect(Method method) {return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);}});}catch (Throwable ex) {.......}//如果沒有找到帶EventListener注解的方法if (CollectionUtils.isEmpty(annotatedMethods)) {this.nonAnnotatedClasses.add(targetType);........}//否則else {// Non-empty set of methods//遍歷for (Method method : annotatedMethods.keySet()) {for (EventListenerFactory factory : factories) {//EventListenerFactory是否支持對該method的處理if (factory.supportsMethod(method)) {Method methodToUse = AopUtils.selectInvocableMethod(method, this.applicationContext.getType(beanName));// 創建事件監聽器ApplicationListener<?> applicationListener =factory.createApplicationListener(beanName, targetType, methodToUse); if (applicationListener instanceof ApplicationListenerMethodAdapter) {((ApplicationListenerMethodAdapter) applicationListener).init(this.applicationContext, this.evaluator);}// 注冊事件到Context中this.applicationContext.addApplicationListener(applicationListener);break;}}}.......}}}小結
processBean的主要業務邏輯:
發布事件
基于@EventListener注解的,發布事件流程和基于接口的一樣,唯一的區別在于
跟進去走到 listener.onApplicationEvent(event) ,基于注解的會走到 ApplicationListenerMethodAdapter實現類中 onApplicationEvent方法,基于注解的是反射調用,而基于接口的形式是直接調用實現類的onApplicationEvent
onApplicationEvent調用了processEvent
反射調用
基于接口,可以參考我的前面的博客: Spring5源碼 - 10 Spring事件監聽機制_應用篇
附 <異步派發和異常處理器>
- 如果事件派發器設置了 Executor,則異步多線程的事件派發
- 如果事件派發器設置了 ErrorHandler,則用異常處理器來處理異常
總結
以上是生活随笔為你收集整理的Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring5源码 - 12 Sprin
- 下一篇: Spring5源码 - 14 如何在所有