Spring事務監聽器@TransactionalEventListener 源碼解析

使用實例

監聽器:

@Component
public class TransactionListener {

    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handler(TransactionEvent transactionEvent) {
        System.out.println(transactionEvent.getSource());
    }
}

帶有事務的業務代碼:

@Override
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void saveUser() {
    User user = new User();
    userMapper.insert(user);
    eventPublisher.publishEvent(newTransactionEvent("事務提交后發布事件1"));
}

源碼:

TransactionalEventListenerFactory:

作用:

這個類用來創建ApplicationListenerMethodTransactionalAdapter對象


image
如何被注冊到spring容器中

@Bean的方式
AbstractTransactionManagementConfiguration這個類被@Configuration修飾


image

下面有個@Bean的方法,創建出TransactionalEventListenerFactory實例


image

EventListenerMethodProcessor

在AnnotationConfigUtils.registerAnnotationConfigProcessors()方法中會把這個類弄成BeanDefinition,注冊到BDRegistry中

image

這個類實現EventListenerMethodProcessor接口的postProcessBeanFactory方法,和BeanFactoryPostProcessor接口的afterSingletonsInstantiated(),其他Bean實例化過程中會調用到這兩個方法

image

創建監聽器

在所有bean實例化之后,實現SmartInitializingSingleton接口的Bean,會被調用到實現該接口的
afterSingletonsInstantiated方法。

DefaultListableBeanFactory.preInstantiateSingletons()

image

這里EventListenerMethodProcessor調用afterSingletonsInstantiated方法


image

從BeanFactoryBean取出所有的BeanName,循環調用processBean方法

image

processBean方法

從bean的Class對象中找出含有@EventListener注解的方法,存到Map<Method, EventListener>中,
@TransactionListenr方法也會被匹配,因為這個注解里打了@EventListener

image

如果從Bean的Class對象中,找到了含有@EventListener注解的方法,循環每一個方法,循環調用EventListenerFactory的子類進行,判斷是否支持該方法的上的注解

//策略模式,如果支持解析該方法的注解,則調用該factory的createApplicationListener方法創建監聽器

  1. TransactionalEventListenerFactory 用來對@TransactionalEventListener修飾的方法創建監聽器


    image
  2. DefaultListenerFactory 用來對@EventListener,@TransactionalEventListener修飾的方法創建監聽器

image
創建ApplicationListenerMethodTransactionalAdapter對象
image

其構造方法將beanName,Class,method對象,賦值到自己的屬性中,并把注冊抽出來了而已

image

創建完監聽器對象后,將其加入到Spring的事務管理器中


image

ApplicationListenerMethodTransactionalAdapter類

image

實現了ApplicationListener接口,說明它是一個監聽器,前面已經加入到事件管理器中,那么根據實現的onApplicationEvent方法的參數類型,決定響應不同類型的事件

image

那么,我們編寫的帶有@TransactionalEventListener注解的方法會在發布事件之后,就會被調用么?

發布事件

注入ApplicationEventPublisher對象

這就是一個上下文ApplicationContext對象,ApplicationContext實現了ApplicationEventPublisher接口

@Autowired
private ApplicationEventPublisher eventPublisher;

發布事件:

image
image

根據時間類型,拿出事件管理器里的監聽器,執行onApplicationEvent方法

image

這個到ApplicationListenerMethodTransactionalAdapter來執行onApplicationEvent方法

image
image
image

創建一個了TransactionSynchronization對象,放到了事務管理器中
TransactionSynchronization

  1. 里面持有:event對象
  2. 由被@TransactionalEventListener修飾的方法封裝而成的監聽器適配器
  3. @TransactionalEventListener的value值(TransactionPhase.AFTER_COMMIT)
image

發布事件的話,后面就沒了,那么事件的觸發在哪里呢?在事務的切面里。

事務提交后,觸發事件

事務切面

提交事務后,會調這個方法

image

取出存放在TransactionSynchronizationManager事務管理器中的TransactionSynchronization,剛才發布事件的時候,往里面存了的哦

image
image

分別調用TransactionSynchronization對象的afterCompletion方法

image
image
image

最后從容器中取出我們編寫的TransactionListener類型的bean,反射調用它的被@TransactionalEventListener修飾的方法

image
image

總結

一般的監聽器

  1. 實現ApplicationListener接口,實現onApplicationEvent方法,
  2. 用@Componnet修飾,ioc容器啟動的時候加入到事件管理器中,獲取手動調用上下文對象的addApplicationListener方法加入
  3. 發布事件,隨即觸發事件

@TransactionalEventListener修飾的監聽器

  1. 每一個被該注解修飾的方法都會創建一個監聽器(持有method對象和當前類的Class),并加入到事件管理器中
  2. 發布事件時,調用上一步創建的監聽器的監聽方法,將該監聽器和必要的信息封裝成對象,放到事務管理器
  3. 由事務切面在提交事務之后,從事務管理器里取出上一步存儲的對象,反射調用我們自己的監聽方法。
需注意點:
  1. 事務監聽方法所在的類一定要注冊到spring容器中,如果沒被實例化,則不會判斷方法中是否存在@TransactionalEventListener注解,不會創建監聽器適配器。
  2. 發布事件一定要在被事務管理的代碼中。如果在事務范圍之外發布事件,事務切面已經結束,則不會去調用監聽器適配器中反射調用我們監聽方法的方法。
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容