Spring事务事件监控

本文详细介绍了Spring事务事件的使用,从实例出发展示了如何通过@TransactionalEventListener注解监听事务事件。接着,深入探讨了其实现原理,包括TransactionSynchronizationManager、ApplicationListenerMethodTransactionalAdapter的角色。最后,提醒在实际应用中注意事件过滤的重要性。
摘要由CSDN通过智能技术生成

前面我们讲到了Spring在进行事务逻辑织入的时候,无论是事务开始,提交或者回滚,都会触发相应的事务事件。本文首先会使用实例进行讲解Spring事务事件是如何使用的,然后会讲解这种使用方式的实现原理。

1. 示例

       对于事务事件,Spring提供了一个注解@TransactionEventListener,将这个注解标注在某个方法上,那么就将这个方法声明为了一个事务事件处理器,而具体的事件类型则是由TransactionalEventListener.phase属性进行定义的。如下是TransactionalEventListener的声明:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EventListener
public @interface TransactionalEventListener {

    // 指定当前标注方法处理事务的类型
	TransactionPhase phase() default TransactionPhase.AFTER_COMMIT;

    // 用于指定当前方法如果没有事务,是否执行相应的事务事件监听器
	boolean fallbackExecution() default false;

    // 与classes属性一样,指定了当前事件传入的参数类型,指定了这个参数之后就可以在监听方法上
    // 直接什么一个这个参数了
	@AliasFor(annotation = EventListener.class, attribute = "classes")
	Class<?>[] value() default {};

    // 作用于value属性一样,用于指定当前监听方法的参数类型
	@AliasFor(annotation = EventListener.class, attribute = "classes")
	Class<?>[] classes() default {};

    // 这个属性使用Spring Expression Language对目标类和方法进行匹配,对于不匹配的方法将会过滤掉
	String condition() default "";

}

       关于这里的classes属性需要说明一下,如果指定了classes属性,那么当前监听方法的参数类型就可以直接使用所发布的事件的参数类型,如果没有指定,那么这里监听的参数类型可以使用两种:ApplicationEvent和PayloadApplicationEvent。对于ApplicationEvent类型的参数,可以通过其getSource()方法获取发布的事件参数,只不过其返回值是一个Object类型的,如果想获取具体的类型还需要进行强转;对于PayloadApplicationEvent类型,其可以指定一个泛型参数,该泛型参数必须与发布的事件的参数类型一致,这样就可以通过其getPayload()方法获取事务事件发布的数据了。关于上述属性中的TransactionPhase,其可以取如下几个类型的值:

public enum TransactionPhase {
    // 指定目标方法在事务commit之前执行
	BEFORE_COMMIT,

    // 指定目标方法在事务commit之后执行
	AFTER_COMMIT,

    // 指定目标方法在事务rollback之后执行
	AFTER_ROLLBACK,
    
    // 指定目标方法在事务完成时执行,这里的完成是指无论事务是成功提交还是事务回滚了
	AFTER_COMPLETION
}

       这里我们假设数据库有一个user表,对应的有一个UserService和User的model,用于往该表中插入数据,并且插入动作时使用注解标注目标方法。如下是这几个类的声明:

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);
  }
}

       上述代码中有一点需要注意的是,对于需要监控事务事件的方法,在目标方法执行的时候需要使用ApplicationEventPublisher发布相应的事件消息。如下是对上述消息进行监控的程序:

@Component
public class UserTransactionEventListener {

  @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
  public void beforeCommit(PayloadApplicationEvent<User> event) {
    System.out.println("before commit, id: " + event.getPayload().getId());
  }

  @TransactionalEventListener(phase = TransactionPhase.AFTER_COMM
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值