在編碼過程當中,咱們常常會遇到完成一個操做須要多個步驟完成的狀況。咱們可能會把多個步驟寫到一個方法裏,假如這個操做須要新增步驟,那麼勢必要修改已有的方法,這違反了開閉原則。spring
咱們能夠使用spring的事件機制來簡單地實現這種功能。Spring的事件機制用到了觀察者模式,何謂觀察者模式?觀察者模式(有時又被稱爲模型(Model)-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟件設計模式的一種。在此種模式中,一個目標物件管理全部相依於它的觀察者物件,而且在它自己的狀態改變時主動發出通知。這一般透過呼叫各觀察者所提供的方法來實現。此種模式一般被用來實現事件處理系統。設計模式
假若有一個下訂單的操做,咱們首先須要建立一個Event繼承ApplicationEvent,並實現構造方法app
import org.springframework.context.ApplicationEvent; public class OrderEvent extends ApplicationEvent { public OrderEvent(Object source) { super(source); } }
接下來須要定義一個OrderService,並注入ApplicationContext對象,向spring發佈下訂單事件OrderEvent,相似以下這樣:ide
import com.study.designer.event.OrderEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; @Service public class OrderService { @Autowired private ApplicationContext applicationContext; public void order() { applicationContext.publishEvent(new OrderEvent("orderService")); } }
向spring發佈了OrderEvent事件以後,須要有對應的Listener來響應這個事件,咱們能夠定義多個事件來監聽這個事件來對應OrderEvent須要的一系列步驟。測試
這裏定義一個OrderSmsListener來虛擬完成短信事件:this
import com.study.designer.event.OrderEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class OrderSmsListener implements ApplicationListener<OrderEvent> { @Override public void onApplicationEvent(OrderEvent orderEvent) { System.out.println("orderSmsListener receive event from " + orderEvent.getSource()); } }
接下來咱們編寫測試用例來驗證功能,能夠看到SMS功能已經正常實現:編碼
import com.study.designer.service.OrderService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class DesignerApplicationTests { @Autowired private OrderService orderService; @Test public void contextLoads() { } @Test public void testOrder() { orderService.order(); } }
查看ApplicationContext的publishEvent方法,發現spring會獲取全部的Listener並向監聽對應事件的Listener廣播事件spa
/** * Publish the given event to all listeners. * @param event the event to publish (may be an {@link ApplicationEvent} * or a payload object to be turned into a {@link PayloadApplicationEvent}) * @param eventType the resolved event type, if known * @since 4.2 */ protected void publishEvent(Object event, @Nullable ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); // Decorate event as an ApplicationEvent if necessary ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<>(this, event); if (eventType == null) { eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType(); } } // Multicast right now if possible - or lazily once the multicaster is initialized if (this.earlyApplicationEvents != null) { this.earlyApplicationEvents.add(applicationEvent); } else { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } // Publish event via parent context as well... if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }