Spring 中的事件機制 ApplicationEventPublisher
Spring 中的事件機制 ApplicationEventPublisher
事件機制在一些大型專案中被經常使用,於是 Spring 專門提供了一套事件機制的介面,方便我們運用。本文來說說 ApplicationEventPublisher 的使用。
在設計模式中,觀察者模式可以算得上是一個非常經典的行為型設計模式,貓叫了,主人醒了,老鼠跑了,這一經典的例子,是事件驅動模型在設計層面的體現。另一模式,釋出訂閱模式往往被人們等同於觀察者模式,但我的理解是兩者唯一區別,是釋出訂閱模式需要有一個排程中心,而觀察者模式不需要,例如觀察者的列表可以直接由被觀察者維護。不過兩者即使被混用,互相替代,通常不影響表達。Java 和 spring 中都擁有 Event 的抽象,分別代表了語言級別和三方框架級別對事件的支援。
Spring 的文件對 Event 的支援翻譯之後描述如下:
ApplicationContext 通過 ApplicationEvent 類和 ApplicationListener 介面進行事件處理。 如果將實現 ApplicationListener 介面的 bean 注入到上下文中,則每次使用 ApplicationContext 釋出 ApplicationEvent 時,都會通知該 bean。本質上,這是標準的觀察者設計模式。
下面通過 demo,看一個電商系統中對 ApplicationEventPublisher 的使用。我們的系統要求,當用戶註冊後,給他傳送一封郵件通知他註冊成功了。然後給他初始化積分,發放一張新使用者註冊優惠券等。
定義一個使用者註冊事件:
public class UserRegisterEvent extends ApplicationEvent{ public UserRegisterEvent(String name) { //name即source super(name); } }
ApplicationEvent 是由 Spring 提供的所有 Event 類的基類,為了簡單起見,註冊事件只傳遞了 name(可以複雜的物件,但注意要了解清楚序列化機制)。
再定義一個使用者註冊服務(事件釋出者):
@Service public class UserService implements ApplicationEventPublisherAware {public void register(String name) { System.out.println("使用者:" + name + " 已註冊!"); applicationEventPublisher.publishEvent(new UserRegisterEvent(name)); } private ApplicationEventPublisher applicationEventPublisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } }
需要注意的是,服務必須交給 Spring 容器託管。ApplicationEventPublisherAware 是由 Spring 提供的用於為 Service 注入 ApplicationEventPublisher 事件釋出器的介面,使用這個介面,我們自己的 Service 就擁有了釋出事件的能力。使用者註冊後,不再是顯示呼叫其他的業務 Service,而是釋出一個使用者註冊事件。
建立郵件服務,積分服務,其他服務(事件訂閱者)等:
@Service public class EmailService implements ApplicationListener<UserRegisterEvent> { @Override public void onApplicationEvent(UserRegisterEvent userRegisterEvent) { System.out.println("郵件服務接到通知,給 " + userRegisterEvent.getSource() + " 傳送郵件..."); } }
事件訂閱者的服務同樣需要託管於 Spring 容器,ApplicationListener 介面是由 Spring 提供的事件訂閱者必須實現的介面,我們一般把該 Service 關心的事件型別作為泛型傳入。處理事件,通過 event.getSource() 即可拿到事件的具體內容,在本例中便是使用者的姓名。 其他兩個 Service,也同樣編寫,實際的業務操作僅僅是列印一句內容即可,篇幅限制,這裡省略。
最後我們使用 Springboot 編寫一個啟動類。
@SpringBootApplication @RestController public class EventDemoApp { public static void main(String[] args) { SpringApplication.run(EventDemoApp.class, args); } @Autowired UserService userService; @RequestMapping("/register") public String register(){ userService.register("xttblog.com"); return "success"; } }
至此,一個電商系統中簡單的事件釋出訂閱就完成了,後面無論如何擴充套件,我們只需要新增相應的事件訂閱者即可。
————————————————
版權宣告:本文為CSDN博主「巨行心」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/ssssny/article/details/104640105