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
方法:app
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,若是不指定事件將能夠接收任何事件,儘可能職責單一。框架
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 方式,看起來更明顯。ide
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
就好了,事件監聽器監聽到事件會自動響應。咱們來寫一個單元測試。單元測試
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獲取更多資訊
this