Spring事件机制
背景简介
当某一个特定事件或动作发生以后,需要执行很多联动动作,如果串行去执行的话太耗时,如果引入消息中间件的话又太重了;这是我们可能想到了观察者模式,但是如何以最简单的方式实现呢,借助spring这个强大的工具,我们可以很容易利用事件和监听器实现。
观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,其主要解决一个对象状态改变给其他关联对象通知的问题,保证易用和低耦合。一个典型的应用场景是:当用户注册以后,需要给用户发送邮件等其他事件。
-
ApplicationEvent:通过继承它,实现自定义事件。另外,通过它的 source 属性可以获取事件源,timestamp 属性可以获得发生时间。
-
ApplicationEventPublisher:通过实现它,来发布变更事件。
-
ApplicationEventListener:通过实现它,来监听指定类型事件并响应动作。
首先定义用户注册事件 UserRegisterEvent。
具体代码实现如下:
首先定义一个事件类
public class UserRegisterEvent extends ApplicationEvent { private String userName; public UserRegisterEvent(Object source, String userName) { super(source); this.userName = userName; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
定义监听器
监听事件第一种方式 实现ApplicationListener接口 ,第二种方式,使用@EventListener注解,@Async可以实现监听的逻辑异步执行前提是在Springboot的启动类上加@EnableAsync注解,异步线程可以自定义,没有自动以的话则会使用spring的默认实现。
监听器的发布顺序是按照 bean 自然装载的顺序执行的,Spring 支持两种方式来实现有序,一是实现SmartApplicationListener,二是使用@Order注解,order注解的值越小优先级越高。
具体的发布顺序实现方式有以下三种:
1:全部实现ApplicationListener接口+@Order注解
2:全部使用@EventListener+@Order注解实现
3:直接实现SmartApplicationListener,重写getOrder方法
@Component public class EmailListener { private final Logger log = LoggerFactory.getLogger(getClass()); @EventListener @Async @Order(1) public void onApplicationEvent(UserRegisterEvent userRegisterEvent) { log.info("user registration email sent successfully,username is :{}", userRegisterEvent.getUserName()); } }
@Component public class WelfareListener { private final Logger log = LoggerFactory.getLogger(getClass()); @EventListener @Async @Order(2) public void addCoupon(UserRegisterEvent event) { log.info("New user registration benefits have been successfully sent,username is: {}", event.getUserName()); } }
public interface UserService { /** * 注册 * * @param username username * @return void * @author liekkas 2021-02-09 12:06 */ void register(String username); }
@Service public class UserServiceImpl implements UserService, ApplicationEventPublisherAware { private final Logger log = LoggerFactory.getLogger(getClass()); private ApplicationEventPublisher applicationEventPublisher; @Override public void register(String username) { log.info("user register event is published!"); applicationEventPublisher.publishEvent(new UserRegisterEvent(this,username)); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } }
注意:如果使用实现ApplicationListener和@EventListener+@Order混合使用,这样的话发布顺序会失效。
发布顺序失效示例:
@Component public class EmailListener implements ApplicationListener<UserRegisterEvent> { private final Logger log = LoggerFactory.getLogger(getClass()); @Override @Async @Order(1) public void onApplicationEvent(UserRegisterEvent userRegisterEvent) { log.info("user registration email sent successfully,username is :{}",userRegisterEvent.getUserName()); } }
@Component public class WelfareListener { private final Logger log = LoggerFactory.getLogger(getClass()); @EventListener @Async @Order(2) public void addCoupon(UserRegisterEvent event) { log.info("New user registration benefits have been successfully sent,username is: {}", event.getUserName()); } }
总结:使用spring的事件监听器模式颗很容易使我们的主业务逻辑与其他的业务逻辑解耦,保证易用和低耦合。