系列文章首發公主號java
事件機制在一些大型項目中被常常使用,因而 Spring 專門提供了一套事件機制的接口,方便咱們運用。本文來講說 ApplicationEventPublisher 的使用。spring
在設計模式中,觀察者模式能夠算得上是一個很是經典的行爲型設計模式,貓叫了,主人醒了,老鼠跑了,這一經典的例子,是事件驅動模型在設計層面的體現。設計模式
另外一模式,發佈訂閱模式每每被人們等同於觀察者模式,但個人理解是二者惟一區別,是發佈訂閱模式須要有一個調度中心,而觀察者模式不須要,例如觀察者的列表能夠直接由被觀察者維護。不過二者即便被混用,互相替代,一般不影響表達。app
java 和 spring 中都擁有 Event 的抽象,分別表明了語言級別和三方框架級別對事件的支持。框架
Spring 的文檔對 Event 的支持翻譯以後描述以下:ide
ApplicationContext 經過 ApplicationEvent 類和 ApplicationListener 接口進行事件處理。 若是將實現 ApplicationListener 接口的 bean 注入到上下文中,則每次使用 ApplicationContext 發佈 ApplicationEvent 時,都會通知該 bean。本質上,這是標準的觀察者設計模式。this
下面經過 demo,看一個電商系統中對 ApplicationEventPublisher 的使用。spa
咱們的系統要求,當用戶註冊後,給他發送一封郵件通知他註冊成功了。翻譯
而後給他初始化積分,發放一張新用戶註冊優惠券等。設計
定義一個用戶註冊事件:
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";
}
}
複製代碼
至此,一個電商系統中簡單的事件發佈訂閱就完成了,後面不管如何擴展,咱們只須要添加相應的事件訂閱者便可。