spring context 子產品裡的ApplicationEventPublisher、EventListener等實作了一個同步的釋出訂閱架構;當然這個架構是跟spring的其他子產品深度耦合的。
@TransactionalEventListener本質上是一個@EventListener,Spring Tx針對使用Transaction時進行了特别的處理;處理過程可見ApplicationListenerMethodTransactionalAdapter;
TransactionalEventListenerFactory類會對将每一個掃描到的注解有TransactionalEventListener包裝成ApplicationListenerMethodTransactionalAdapter對象;
通過ApplicationListenerMethodTransactionalAdapter的onApplicationEvent方法可以看到
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronization transactionSynchronization = createTransactionSynchronization(event);
TransactionSynchronizationManager.registerSynchronization(transactionSynchronization);
}
else if (this.annotation.fallbackExecution()) {
if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK && logger.isWarnEnabled()) {
logger.warn("Processing " + event + " as a fallback execution on AFTER_ROLLBACK phase");
}
processEvent(event);
}
else {
// No transactional event execution at all
if (logger.isDebugEnabled()) {
logger.debug("No transaction is active - skipping " + event);
}
}
}
當使用ApplicationEventPublisher public一個對象的時候,此監聽器就會監聽到,并将釋出的對象、将注解有TransactionalEventListener包裝成的ApplicationListenerMethodTransactionalAdapter和TransactionalEventListener注解上指定的TransactionPhase一同組裝成TransactionSynchronizationEventAdapter對象,這個對象是一個TransactionSynchronization的實作,随後将此TransactionSynchronization對象通過TransactionSynchronizationManager注冊;TransactionSynchronizationEventAdapter注冊到目前事務之後,就可以在事務執行過程通過回調TransactionSynchronizationEventAdapter對應的方法,間接調用到将注解有TransactionalEventListener包裝成的ApplicationListenerMethodTransactionalAdapter的邏輯了;
關于TransactionSynchronizationManager和TransactionSynchronization不太明白的,可以搜尋一下其作用,可以先這麼了解,TransactionSynchronization是一個接口,其裡面定義了一個事務執行過程中重要時間點的回調方法,TransactionSynchronizationManager通過ThreadLocal管理注冊到事務的多個TransactionSynchronization;
典型的使用過程如下:
public class User {
private long id;
private String name;
private int age;
// getter and setter...
}
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private ApplicationEventPublisher publisher;
@Override
public void insert(User user) {
jdbcTemplate.update("insert into user (id, name, age) value (?, ?, ?)",
user.getId(), user.getName(), user.getAge());
publisher.publishEvent(user);
}
}
insert方法事務攔截器攔截,執行完方法之後,也就釋出了一個事件,由于spring的事件釋出訂閱是同步的,也就是說,執行完publisher.publishEvent(user),釋出事件之後,在一個線程中,接着回調訂閱的邏輯;在此處,這個回調的邏輯也就是ApplicationListenerMethodTransactionalAdapter的onApplicationEvent方法,上面已經解析完這個方法的内容,此方法最重要的邏輯是建構一個TransactionSynchronization對象,并注冊給目前事務;