前段时间看到同事在项目里面使用了一个叫做 @EventLintener 的注解。
在这之前,我知道这个注解的用法和想要达到的目的,但是也仅限于此,其内部工作原理对我来说是一个黑盒,我完完全全不知道它怎么就实现了“监听”的效果。
现在既然已经出现在项目里面了,投入上生产上去使用了,所以我打算盘一下它,以免以后碰到问题的时候错过一个装逼的...
哦,不。
错过一个表现自己的机会。
Demo
首先,按照歪歪歪师傅的老规矩,第一步啥也别说,先搞一个 Demo 出来,没有 Demo 的源码解读,就像是吃面的时候没有大蒜,差点意思。
先铺垫一个背景吧。
假设现在的需求是用户注册成功之后给他发个短信,通知他一下。
正常来说,伪代码很简单:
boolean success = userRegister(user); if(success){
sendMsg("客官,你注册成功了哦。记得来玩儿~");
}
这代码能用,完全没有任何问题。但是,你仔细想,发短信通知这个动作按理来说,不应该和用户注册的行为“耦合”在一起,难道你短信发送的时候失败了,用户就不算注册成功吗?
上面的代码就是一个耦合性很强的代码。
怎么解耦呢?
应该是在用户注册成功之后,发布一个“有用户注册成功了”的事件:
boolean success = userRegister(user); if(success){
publicRegisterSuccessEvent(user);
}
然后有地方去监听这个事件,在监听事件的地方触发“短信发送”的动作。
这样的好处是后续假设不发短信了,要求发邮件,或者短信、邮件都要发送,诸如此类的需求变化,我们的用户注册流程的代码不需要进行任何变化,仅仅是在事件监听的地方搞事情就完事了。
这样就算是完成了两个动作的“解耦”。
怎么做呢?
我们可以基于 Spring 提供的 ApplicationListener 去做这个时间。
我的 Demo 里面用的 Spring 版本是 5.2.10。
这次的 Demo 也非常的简单,我们首先需要一个对象来封装事件相关的信息,比如我这里用户注册成功,肯定要关心的是 userName:
@Data
public class RegisterSuccessEvent {
private String userName;
public RegisterSuccessEvent(String userName) {
this.userName = userName;
}
}
我这里只是为了做 Demo,对象很简单,实际使用过程中,你需要什么字段就放进去就行。
然后需要一个事件的监听逻辑:
@Slf4j
@Component
public class RegisterEventListener {
@EventListener
public void handleNotifyEvent(RegisterSuccessEvent event) {
log.info("监听到用户注册成功事件:" +
"{},你注册成功了哦。记得来玩儿~", event.getUserName());
}
}
接着,通过 Http 接口来进行事件发布:
@Resource
private ApplicationContext applicationContext;
@GetMapping("/publishEvent")
public void publishEvent() {
applicationContext.publishEvent(new RegisterSuccessEvent("歪歪"));
}
最后把服务启动起来,调用一次:
输出正常,完事儿,这个 Demo 就算是搞定了,就只有十多行代码。
这么简单的 Demo 你都不想亲自动手去搭一个的话,想要靠肉眼学习的话,那么我只能说: