观察者模式(Observe Pattern)
定义对象之间的一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
业务开发中,观察者模式对我们很大的一个作用,在于实现业务的解耦。
spring事件机制
Spring 基于观察者模式,实现了自身的事件机制,由三部分组成:
- 事件 ApplicationEvent:通过继承它,实现自定义事件。另外,通过它的 source 属性可以获取事件源,timestamp 属性可以获得发生时间。
- 事件发布者 ApplicationEventPublisher:通过它,可以进行事件的发布。
- 事件监听器 ApplicationListener:通过实现它,进行指定类型的事件的监听。
JDK 也内置了事件机制的实现,考虑到通用性,Spring 的事件机制是基于它之上进行拓展。
因此, ApplicationEvent 继承自 java.util.EventObject
ApplicationListener 继承自 java.util.EventListener。
依赖
<!-- 实现对 Spring MVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1. 自定义事件
继承 ApplicationEvent 类
public class UserRegisterEvent extends ApplicationEvent {
/**
* 用户名
*/
private String username;
public UserRegisterEvent(Object source) {
super(source);
}
public UserRegisterEvent(Object source, String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
}
2. 发布类
@Service
public class UserService implements ApplicationEventPublisherAware { // <*>
private Logger logger = LoggerFactory.getLogger(getClass());
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void register(String username) {
// ... 执行注册逻辑
logger.info("[register][执行用户({}) 的注册逻辑]", username);
// <*> ... 发布
applicationEventPublisher.publishEvent(new UserRegisterEvent(this, username));
}
}
3. 监听类
第一种
@Service
public class EmailService implements ApplicationListener<UserRegisterEvent> { // <*>
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
@Async // <1>
public void onApplicationEvent(UserRegisterEvent event) { // <*>
logger.info("[onApplicationEvent][给用户({}) 发送邮件]", event.getUsername());
}
}
【可以不加】<1> 处,设置 @Async 注解,声明异步执行。毕竟实际场景下,发送邮件可能比较慢,又是非关键逻辑。
第二种
@Service
public class CouponService {
private Logger logger = LoggerFactory.getLogger(getClass());
@EventListener // <1>
public void addCoupon(UserRegisterEvent event) {
logger.info("[addCoupon][给用户({}) 发放优惠劵]", event.getUsername());
}
}
spring内置权限
配置监听顺序
更多文章参考: 阿里语雀