Spring是基於事件驅動模型的,事件驅動模型也就是我們常說的觀察者,或者發布-訂閱模型。
Spring 的事件角色的類圖如下:

spring中的這些接口和抽象類:
- ApplicationEventPublisherAware:接口,用來發布事件
- ApplicationEvent :抽象類,用來定義事件
- ApplicationListener<E extends ApplicationEvent>:接口,用來監聽事件,可以在這里實現自己的處理邏輯。
事件定義
/** * 定義事件 */ public class UserRegisterEvent extends ApplicationEvent { public UserRegisterEvent(String name) { //name即source super(name); } }
事件發布
@Service public class UserService implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } public void register(String name) { System.out.println("用戶:" + name + " 已注冊!"); applicationEventPublisher.publishEvent(new UserRegisterEvent(name)); } }
為了方便,我們可以單獨創建一個發布事件的類。
@Component public class SpringEventHelper implements ApplicationEventPublisherAware { private static ApplicationEventPublisher applicationEventPublisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { if (null == SpringEventHelper.applicationEventPublisher) { SpringEventHelper.applicationEventPublisher = applicationEventPublisher; } } public static void publishEvent(ApplicationEvent event) { SpringEventHelper.applicationEventPublisher.publishEvent(event); } }
這樣上面發布事件的代碼就改為:
@Service public class UserService { public void register(String name) { System.out.println("用戶:" + name + " 已注冊!"); SpringEventHelper.publishEvent(new UserRegisterEvent(name)); } }
事件訂閱(監聽者)
/** * 事件監聽者,可以自定義處理邏輯 */ @Component public class EmailHandler implements ApplicationListener<UserRegisterEvent> { @Override public void onApplicationEvent(UserRegisterEvent userRegisterEvent) { System.out.println("郵件服務接到通知,給 " + userRegisterEvent.getSource() + " 發送郵件..."); } }
基於注解的監聽@EventListener
@Component public class SmsHandler{ @EventListener public void createSmsEvent(UserRegisterEvent event){ System.out.println("短信服務接到通知,給 " + event.getSource() + " 發送短信..."); } }
異步事件
上面的監聽事件都是同步觸發的,如果想異步只需要兩步:
- 啟動類(SpringBoot)或Spring配置類上添加 @EnableAsync注解,開啟異步支持。
- 所有事件監聽方法上添加 @Async注解
@Component public class SmsHandler{ @Async @EventListener public void createSmsEvent(UserRegisterEvent event){ System.out.println("短信服務接到通知,給 " + event.getSource() + " 發送短信..."); } }
事件傳播機制
當我們監聽一個事件處理完成時,還需要發布另一個事件,一般我們想到的是調用ApplicationEventPublisher#publishEvent發布事件方法,但Spring提供了另一種更加靈活的新的事件繼續傳播機制,監聽方法返回一個事件,也就是方法的返回值就是一個事件對象。
假設現在有一個唱歌的事件和唱歌的監聽
/** * @Description 事件 */ public class UserSingEvent extends ApplicationEvent { public UserSingEvent(String name) { super(name); } } /** * @Description 監聽者 */ @Component public class UserSingHandler { @EventListener public void createSingEvent(UserSingEvent event) { System.out.println("接到通知,給 " + event.getSource() + " 唱了一首【一剪梅】..."); } }
則上面發短信的事件訂閱者可以改為:
@Component public class SmsHandler{ @EventListener public UserSingEvent createSmsEvent(UserRegisterEvent event){ System.out.println("短信服務接到通知,給 " + event.getSource() + " 發送短信..."); String name = (String) event.getSource(); return new UserSingEvent(name); // 發布另外一個事件 } }
完整示例:創建訂單
(1)訂單實體類
public class Order { private String orderNo; private String orderStatus; private String goods; private Date createTime; public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public String getOrderStatus() { return orderStatus; } public void setOrderStatus(String orderStatus) { this.orderStatus = orderStatus; } public String getGoods() { return goods; } public void setGoods(String goods) { this.goods = goods; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } }
(2)創建訂單的事件定義
public class OrderCreateEvent extends ApplicationEvent { private final Order order; public OrderCreateEvent(Object source, Order order) { super(source); this.order = order; } public Order getOrder() { return order; } }
(3)發布事件
@Service public class OrderService { /** * 訂單保存 */ public void save() { Order order = new Order(); order.setOrderNo("1"); order.setGoods("手機"); System.out.println("訂單保存成功:" + order.toString()); //發布事件 SpringEventHelper.publishEvent(new OrderCreateEvent(this, order)); } }
(4)事件訂閱
@Component public class OrderCreateEventListener implements ApplicationListener<OrderCreateEvent> { @Override public void onApplicationEvent(OrderCreateEvent event) { System.out.printf(this.getClass().getName() + " -- ApplicationListener 接口實現,訂單號[%s]:,商品[%s]\n", event.getOrder().getOrderNo(), event.getOrder().getGoods()); } }
(5)測試
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {SpringConfig.class}) @WebAppConfiguration //全注解的形式必須添加@WebAppConfiguration注解 public class ContextTest { @Autowired private OrderService orderService; @Test public void test(){ orderService.save(); } }
參考
