Java 開發中有些邏輯是這樣的,完成了A操做,再繼續B操做,在繼續C操做。這麼描述好像有點不清楚。打個比方把,你吃晚飯,通知你老婆(女朋友)來收碗筷,而後通知你的線上兄弟告訴他們你回來了準備開黑。至於你老婆(女朋友)來不來收拾無所謂,反正你告訴她了。至於你兄弟你也是通知他們,人家也不必定組你,萬一他們正在跟一個一拖三的carry大佬玩的正起勁兒呢。java
吃晚飯就是一個所謂的事件。觸發了隨後的兩個操做,他們只存在因果關係。可是它們互不干擾,各自爲政。一個完整的事件由 事件源、事件發佈、事件監聽 組成。 接下來咱們聊聊 Spring 中的事件。git
Spring 框架中使用了大量的事件機制,好比 Spring Boot 的啓動。方便起見咱們新建一個 Spring Boot 工程。而後跟着我一步步的來進行事件的操做。spring
org.springframework.context.ApplicationEvent
來編寫事件。時間裏定義好事件推送到監聽器須要執行的方法,固然也能夠在監聽器裏寫觸發邏輯。咱們來聲明一下:package cn.felord.boot.event; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; /** * 吃飯事件 * * @author dax * @since 2019 /7/8 21:54 */ @Slf4j public class EatEvent extends ApplicationEvent { private Boolean eatFinished; /** * Instantiates a new Eat event. * * @param eatFinished 吃飯是否完成的信號 這裏也能夠傳遞其餘資源 */ public EatEvent(Boolean eatFinished) { super(eatFinished); this.eatFinished = eatFinished; } /** * 這裏會由對應監聽器{@link ApplicationListener<EatEvent>} 執行 * * 叫女朋友收拾碗筷. */ public void callGirlFriend() { log.info("親愛的! 我吃完飯了,來收拾收拾吧"); } /** * 這裏會由對應監聽器{@link ApplicationListener<EatEvent>} 執行 * 呼叫兄弟開黑. */ public void callBrothers() { log.info("兄弟們! 我吃完飯了,帶我開黑"); } /** * 吃晚飯的信號. * * @return the boolean */ public Boolean isEatFinished() { return this.eatFinished; } }
發佈事件經過實現事件發佈接口 org.springframework.context.ApplicationEventPublisher
或者其門面接口 org.springframework.context.ApplicationEventPublisherAware
, 推薦門面接口,裏面要定義一個主動推送事件的方法以下面的 refreshEvent
方法,實際代理了 ApplicationEventPublisher
執行其 publishEvent
方法:segmentfault
package cn.felord.boot.event; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; /** * 發佈事件 發佈事件經過實現 事件發佈接口 {@link ApplicationEventPublisher} * 或者經過門面接口{@link ApplicationEventPublisherAware} * 推薦按照下面的實現方式,並且該類須要註冊爲spring bean * * @author dax * @since 2019 /7/8 22:04 */ @Slf4j public class EatEventPublisherAware implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; private ApplicationEvent eatEvent; public EatEventPublisherAware(ApplicationEvent eatEvent) { this.eatEvent = eatEvent; } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } /** * 發送事件動做 事件的動做須要主動觸發 調用此方法進行事件觸發 * 代理{@link ApplicationEventPublisher#publishEvent(ApplicationEvent)} */ public void refreshEvent() { log.info("發送事件中……"); this.applicationEventPublisher.publishEvent(eatEvent); } }
事件監聽用來監聽事件以觸發相關的邏輯。經過實現 org.springframework.context.ApplicationListener<E extends ApplicationEvent>
來實現事件的監聽。特別注意泛型E,若是不指定事件將能夠接收任何事件,儘可能職責單一。app
package cn.felord.boot.event; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationListener; /** * {@link EatEvent}事件的專屬事件監聽器 * @author dax * @since 2019/7/8 22:11 */ @Slf4j public class EatEventListener implements ApplicationListener<EatEvent> { @Override public void onApplicationEvent(EatEvent eatEvent) { //若是吃完飯了 if (eatEvent.isEatFinished()) { eatEvent.callGirlFriend(); log.error("來自母老虎的咆哮:滾犢子"); eatEvent.callBrothers(); log.error("太晚了,咱們已經滿了,明天帶你"); log.info("仍是關注一下 【碼農小胖哥】 學習點新知識吧"); } } }
將上面三個類注入 Spring
容器中,這裏咱們採用了 JavaConfig 方式,看起來更明顯。框架
package cn.felord.boot.config; import cn.felord.boot.event.EatEvent; import cn.felord.boot.event.EatEventListener; import cn.felord.boot.event.EatEventPublisherAware; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 這三個必定要配置成bean * * @author dax * @since 2019/7/8 22:16 */ @Configuration public class EventConfig { @Bean public ApplicationEvent eatEvent() { return new EatEvent(true); } @Bean public ApplicationListener eatEventListener() { return new EatEventListener(); } @Bean public ApplicationEventPublisherAware eatEventPublisherAware(ApplicationEvent eatEvent) { return new EatEventPublisherAware(eatEvent); } }
這裏就大功告成了,那麼如何使用呢,執行事件發佈器的發佈方法 refreshEvent
就好了,事件監聽器監聽到事件會自動響應。咱們來寫一個單元測試。ide
package cn.felord.boot; import cn.felord.boot.event.EatEventPublisherAware; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; @RunWith(SpringRunner.class) @SpringBootTest public class EventSpringApplicationTests { @Resource private EatEventPublisherAware eatEventPublisherAware; @Test public void contextLoads() { eatEventPublisherAware.refreshEvent(); } }
運行一下,入圖單元測試
到此你應該就學會使用 Spring 事件了,這樣寫出來的代碼逼格更高。還能提現你對 Spring 框架的一些理解。固然還有一種更加簡單的、基於註解的方式,這裏再也不闡述。相關代碼在個人 碼雲倉庫學習
關注公衆號:Felordcn 獲取更多資訊
測試