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对象,并注册给当前事务;