关于@EventListener的一些使用

1.@EventListener是什么?

 @EventListener是spring中用于声明监听器的注解,spring声明监听器有两种方式:

1.实现ApplicationListener接口

2.使用@EventListener声明在某个方法上。

2.@EventListener怎么用

首先我们模拟一个用户注册的场景,比如要做个一个app,需求是用户注册完,需要发送短信给用户,新手上来肯定是这么做

下面是伪代码

@PostMapping(value = "/register")
    @Transactional(rollbackFor ={RuntimeException.class, Exception.class})
    public String registerUser(@RequestBody UserVO userVO){

        User user=new User();
        user.setUserName(userVO.getUserName());
        user.setPassWord(userVO.getPassWord());
        //插入数据库
        userMapper.insert(user);
        //调用发送短信接口
        emailService.sendMessage(user)

        return "注册成功";
    }

齐活!代码一提交,发到测试环境,让测试跑遍流程,关机下班,弗雷尔卓德我来了!

第二天上班,产品经理顶着稀疏的头发,战战兢兢地跟你说:老板临时决定,要增加注册成功后发送邮件的功能,你表面佯装生气,其实内心窃喜:我在方法下面加个发送邮件的方法不就行了。于是你咔咔开干,代码提交,发到测试环境,让测试跑遍流程,关机下班,金铲铲我来了!

第三天上班,产品经理准时出现在了你的工位旁边,颤抖着跟你说:哥 老板说发短信有点费钱,让取消掉发短信的功能。这次你是真的生气了,冲着产品经理大喊:怎么来回变需求!我代码都改好几遍了!测试也在旁边默默流泪,心想又得再测一遍功能了。

但是,业务不是一成不变的,不会像1+1=2那样永远不变,是随着市场动态调节的,我们把控不了市场的节奏,只能去提升自己的代码,使其变得更加灵活。下面开始改造。

首先明确主逻辑是用户注册的功能,发送短信或者邮件,其实都是附加的功能,就算没有这些,也不会影响用户正常使用。这个时候就可以使用sping的监听功能,用户注册完后,发送一个广播,监听用户注册事件的监听器收到广播后,会去执行自己的逻辑,这样有个好处:做到了业务解耦,不管你是发送短信或者发送邮件,你只需要监听用户注册事件就行,就算以后多个发送微信提醒的功能,只需要写个方法,然后监听用户注册事件即可,不需要侵入原有的用户注册代码。不多说,开干!

1.首先定义一个继承ApplicationEvent的类

@Getter
@Setter
public class RegisterSuccessEvent extends ApplicationEvent {
    private UserVO userVO;
    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public RegisterSuccessEvent(UserVO source) {
        super(source);
        this.userVO=source;
    }
}

2.定义一个监听类

@Component
@Slf4j
public class RegisterSuccessListener {

    @EventListener
    @Order(1)
    public void handleEamil(RegisterSuccessEvent registerSuccessEvent) {

        log.info("给用户{}发送邮件成功", registerSuccessEvent.getUserVO().getUserName());
    }

   @EventListener
    @Order(2)
    public void handlePrice(RegisterSuccessEvent registerSuccessEvent) {
        log.info("给用户{}发送优惠券成功", registerSuccessEvent.getUserVO().getUserName());
    }

    @EventListener
    @Order(3)
    public void handleMessage(RegisterSuccessEvent registerSuccessEvent) {
        log.info("给用户{}发送短信成功", registerSuccessEvent.getUserVO().getUserName());
    }

这样当监听类监听到用户注册事件后,会执行监听方法。就算要去掉某个功能,直接注释掉这个功能方法上面的注解即可。

当然也可以通过@Order注解来控制监听方法的执行顺序。

但是这种会存在一种情况,就是用户注册事务和发送信息事务,是同一个事务,如果注册用户失败,或者发送信息失败,都会出现问题,影响用户体验,解决这个问题的方法有好几种,我介绍一下其中一种,就是用@TransactionalEventListener注解替代@EventListener。

Spring的事件监听机制(发布订阅模型)实际上并不是异步的(默认情况下),而是同步的来将代码进行解耦。即处理事件和发布事件的线程是同一个。可以通过@Async进行异步处理。而@TransactionEventListener仍是通过这种方式,只不过加入了回调的方式来解决,这样就能够在事务进行Commited,Rollback…等的时候才会去进行Event的处理,达到事务同步的目的。

@TransactionalEventListener可以通过phase属性指定触发阶段,有四种:

  1. BEFORE_COMMIT:在事务提交之前触发事件。
  2. AFTER_COMMIT:在成功完成提交后触发事件。这是默认的触发阶段。
  3. AFTER_ROLLBACK:如果事务已回滚,则触发事件。
  4. AFTER_COMPLETION:事务完成之后(无论是提交还是回滚)进行触发。如果同时注册AFTER_COMPLETION和AFTER_ROLLBACK/AFTER_COMMIT事件,那么触发的先后顺序是不固定的,但是可以使用@Order注解指定先后顺序。

 @TransactionalEventListener标注的监听器方法,在默认情况下仅仅会被事务中发布的事件触发,如果需要在没有事务也能当作普通时间监听器触发,那么需要将fallbackExecution属性设置为true。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值