在實(shí)際項(xiàng)目中,我們往往需要自定義一些事件和監(jiān)聽(tīng)器來(lái)滿(mǎn)足業(yè)務(wù)場(chǎng)景,比如在微服務(wù)中會(huì)有這樣的場(chǎng)景:
服務(wù) A 在處理完某個(gè)邏輯之后,需要通知微服務(wù) B 去處理另一個(gè)邏輯,或者微服務(wù) A 處理完某個(gè)邏輯之后,需要將數(shù)據(jù)同步到微服務(wù) B,這種場(chǎng)景非常普遍,這個(gè)時(shí)候,我們可以自定義事件以及監(jiān)聽(tīng)器來(lái)監(jiān)聽(tīng),一旦監(jiān)聽(tīng)到微服務(wù) A 中的某事件發(fā)生,就去通知微服務(wù) B 處理對(duì)應(yīng)的邏輯。
步驟1, 自定義事件A
public class MyEvent extends ApplicationEvent { private User user; public MyEvent(Object source, User user) { super(source); //這里寫(xiě)服務(wù)A的內(nèi)容,如下 this.user = user; ystem.out.println("A服務(wù)完成"); } public User getUser() { return user; } }
步驟2, 監(jiān)聽(tīng)事件A,在監(jiān)聽(tīng)事件中 實(shí)現(xiàn)B或者B
@Component public class MyEventListener implements ApplicationListener<MyEvent> { public void onApplicationEvent(MyEvent myEvent) { User user = myEvent.getUser(); // 一旦MyEvent事件發(fā)生,這里就會(huì)執(zhí)行 // 處理事件,實(shí)際項(xiàng)目中可以通知?jiǎng)e的微服務(wù)或者處理其他邏輯等等 System.out.println("用戶(hù)名:" + user.getUsername()); System.out.println("密碼:" + user.getUserpwd()); System.out.println("監(jiān)聽(tīng)事件發(fā)生后, 通知的服務(wù)已經(jīng)完成"); } }
步驟3,發(fā)布事件
@Service public class UserService { @Resource private ApplicationContext applicationContext; /** * 發(fā)布事件 * @return */ public User getUser2() { User user = new User(1L, "莊子", "123456"); //發(fā)布事件 MyEvent event = new MyEvent(this, user); applicationContext.publishEvent(event); return user; } }
在 service 中注入 ApplicationContext,在業(yè)務(wù)代碼處理完之后,通過(guò) ApplicationContext 對(duì)象手動(dòng)發(fā)布 MyEvent 事件,這樣我們自定義的監(jiān)聽(tīng)器就能監(jiān)聽(tīng)到,然后處理監(jiān)聽(tīng)器中寫(xiě)好的業(yè)務(wù)邏輯。
最后,在 Controller 中寫(xiě)一個(gè)接口來(lái)測(cè)試一下
@Resource private UserService userService; @GetMapping("/publish") public String eventPublish() { userService.getUser2(); return "success"; }
執(zhí)行流程:調(diào)用服務(wù),發(fā)布事件,事件發(fā)布后,會(huì)被監(jiān)聽(tīng)到
瀏覽器訪(fǎng)問(wèn) http://localhost:8001/listener/publish