Spring框架通过发布订阅模式为组件间通信提供了高效且松散耦合的解决方案,提升了系统的灵活性和扩展性。
本文将探讨该模式的原理、实现、应用场景及其优势与挑战。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
-
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
-
视频教程:https://doc.iocoder.cn/video/
发布订阅模式,又称为观察者模式(
Observer Pattern
)的一种变体,是一种基于消息传递的设计模式。在这个模式中,主要涉及三个核心角色:
发布者(
Publisher
)
、
订阅者(
Subscriber
)
和
消息代理(
Message Broker
)
。
-
发布者是消息的产生者
,它负责生成特定类型的消息并将其发送到消息代理。发布者不需要了解有哪些订阅者对其发布的消息感兴趣,它只专注于消息的生成和发布。
-
订阅者则是对特定类型消息感兴趣的组件
,它们向消息代理注册自己感兴趣的消息类型。当消息代理接收到发布者发送的符合订阅者兴趣的消息时,会将消息转发给对应的订阅者。订阅者可以根据接收到的消息进行相应的业务处理。
-
消息代理是发布者和订阅者之间的中介
,它负责接收发布者的消息,并根据订阅者的注册信息将消息分发给相应的订阅者。消息代理的存在使得发布者和订阅者之间实现了高度的解耦,它们不需要直接相互引用或通信,只需要与消息代理进行交互即可。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
-
项目地址:https://github.com/YunaiV/yudao-cloud
-
视频教程:https://doc.iocoder.cn/video/
下面通过发布订阅模式实现一个示例:在用户注册成功后,系统自动发送邮件通知用户。
定义事件类,事件类通常继承自
org.springframework.context.ApplicationEvent
我们可以定义一个
UserRegisteredEvent
类来表示用户注册成功的事件
public class UserRegisteredEvent extends ApplicationEvent {
// 这里的User是一个包含用户相关信息的实体类
private User user;
// source:事件的源对象,用于表明这个事件是由哪个对象触发的
// 具体作用下面订阅事件中解释
public UserRegisteredEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
发布事件的组件需要获取
ApplicationEventPublisher
实例,并通过它来发布事件
在用户注册操作成功完成后,发布用户注册事件
@Service
public class UserRegistrationService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void registerUser(User user) {
// 执行用户注册逻辑,如保存用户信息到数据库等
// 注册成功后发布事件
UserRegisteredEvent event = new UserRegisteredEvent(this, user);
eventPublisher.publishEvent(event);
}
}
3.1、ApplicationListener接口
订阅者可以通过实现
org.springframework.context.ApplicationListener
接口来订阅特定的事件
发送欢迎邮件的服务可以订阅
UserRegisteredEvent
事件
@Component
public class WelcomeEmailSender implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 发送欢迎邮件给用户的逻辑,如调用邮件发送接口等
System.out.println("Sending welcome email to " + user.getEmail());
}
}
3.2、@EventListener注解
除了基于接口的订阅方式,Spring还提供了
@EventListener
注解来简化订阅者的实现。
Spring还提供了对异步事件的支持,可以使用@Async注解来实现异步处理,从而避免阻塞事件的发布者
@Component
public class AnotherWelcomeEmailSender {
@EventListener
@Async
public void handleUserRegisteredEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 发送欢迎邮件的逻辑
System.out.println("Another welcome email sent to " + user.getEmail());
}
}
3.3、事件源Object source的作用
假设有一个Web服务和一个API服务都可能触发
UserRegisteredEvent
事件,你可以在监听器中根据source进一步区分事件的处理方式
@EventListener
public void onUserRegistered(UserRegisteredEvent event)