Spring 中的發布-訂閱模式
發布訂閱模式是怎樣的?
現在市面上流行的很多消息中間件就是采用的該種模式,這種模式 在實際業務中 將 事件發布者(Publisher) 與 事件訂閱者 (Subscriber)通過額外的事件通道(Event Channel)來解耦,其基本原理與先前提到的觀察者模式有些許類似,但發布訂閱模式額外存在了Event Channel 的概念,也因此解決了 主題(Subject)和 Observer(觀察者)之間的耦合,發布者和訂閱者就交互細節上不再需要相互關聯,下圖可以看到兩種模式之間的區別。

在 Spring 中的實際應用
在Spring框架中,發布-訂閱模式是通過事件驅動的方式實現的,用于解耦應用程序中的組件。Spring的事件機制允許應用程序中的各個部分以松散耦合的方式進行通信,這種方式在日常編碼中最適合應對一些需要狀態機的業務模型, 下面就來講下 在 Spring 中的發布訂閱涉及到的概念
- 事件(Event):事件是應用程序中的狀態變化或動作,對應于某個特定的行為或狀態。在Spring中,事件通常是一個POJO(Plain Old Java Object)類,它包含了與該事件相關的信息。
- 事件發布者(Event Publisher):事件發布者是負責發布事件的組件。在Spring中,ApplicationContext(應用程序上下文)充當了事件發布者的角色。通過ApplicationContext,應用程序可以發布事件,并將其傳遞給已注冊的事件監聽器。
- 事件訂閱者(Event Subscriber):事件訂閱者是負責處理特定類型事件的組件。在Spring中,事件訂閱者通常是實現了ApplicationListener接口的類,用于監聽并處理發布的事件。
- 事件推送(ApplicationEventPublisher):事件推送是指通過ApplicationEventPublisher接口在Spring中發布事件的過程。這個接口可以在ApplicationContext中使用,用于向已注冊的監聽器廣播事件的發生。
設計步驟
- 定義事件類:首先,定義應用中的各種事件,這些事件可以是任何與應用狀態變化或行為相關的事情。事件通常是簡單的POJO類。
- 定義發布者:創建事件發布者(Publisher)組件,它負責發布事件。在Spring中,你可以使用ApplicationEventPublisher接口或者直接在Bean方法上標注@EventListener注解來實現。
- 定義訂閱者:創建事件訂閱者(Subscriber)組件,它負責訂閱感興趣的事件并對事件做出響應。在Spring中,你可以定義實現ApplicationListener接口的類來作為事件監聽器,或者使用@EventListener注解在方法上訂閱事件。
- 觸發事件:在適當的時候,通過發布者發布事件。一旦事件被發布,所有已經注冊的訂閱者將會收到事件通知并執行相應的邏輯。
這里會以簡單的 用戶注冊的場景來介紹下 Spring ApplicationEventPublisher 的使用方式
定義事件類UserRegisteredEvent
import org.springframework.context.ApplicationEvent;
public class UserRegisteredEvent extends ApplicationEvent {
private final String username;
public UserRegisteredEvent(Object source, String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
}
創建UserRegistrationService服務,負責注冊新用戶并發布事件
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
public class UserRegistrationService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void registerUser(String username) {
// 注冊新用戶邏輯
// ...
// 發布用戶注冊事件,這里使用 eventPublisher 將 預先定義好的事件交由 Spring 的Event Channel 管理
eventPublisher.publishEvent(new UserRegisteredEvent(this, username));
}
}
創建UserNotificationService服務,訂閱UserRegisteredEvent事件并發送通知
@Service
public class UserNotificationService {
@EventListener
public void handleUserRegisteredEvent(UserRegisteredEvent event) {
// 處理用戶注冊事件,例如發送通知
String username = event.getUsername();
System.out.println("Notification sent for user: " + username);
}
}
創建 Spring 啟動類
@SpringBootApplication
@RequiredArgsConstructor
public class Application implements CommandLineRunner {
private final UserRegistrationService userRegistrationService;
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setWebApplicationType(WebApplicationType.NONE);
app.run(args);
}
@Override
public void run(String... args) {
// 在啟動時注冊新用戶
userRegistrationService.registerUser("peng");
}
}
最后程序的輸出結果 如下所示:
Notification sent for user: peng
案例中的代碼已發布在 github倉庫 , 路徑為package com.github.meeting.demo.pattern.pubsub;.

浙公網安備 33010602011771號