詳解SpringBoot 發(fā)布ApplicationEventPublisher和監(jiān)聽ApplicationEvent事件
資料地址
實(shí)現(xiàn)方法
- 自定義需要發(fā)布的事件類,需要繼承ApplicationEvent類或PayloadApplicationEvent<T>(該類也僅僅是對ApplicationEvent的一層封裝)
- 使用@EventListener來監(jiān)聽事件
- 使用ApplicationEventPublisher來發(fā)布自定義事件(@Autowired注入即可)
/**
* 自定義保存事件
* @author peter
* 2019/1/27 14:59
*/
public class PersonSaveEvent<DATA> extends ApplicationEvent {
private DATA data;
public PersonSaveEvent(DATA source) {
super(source);
this.data = source;
}
public DATA getData() {
return data;
}
}
//發(fā)布事件
public void savePerson(Person person){
personDao.save(person);
publisher.publishEvent(new PersonSaveEvent<>(1));
}
//監(jiān)聽事件
@EventListener
public void listenEvent(PersonSaveEvent<Integer> event) {
System.out.println("監(jiān)聽到PersonSaveEvent事件; 接收到的值:" + event.getData() + ";發(fā)布的時間為" + Instant.ofEpochMilli(event.getTimestamp()));
}
好處
可以使核心業(yè)務(wù)與子業(yè)務(wù)進(jìn)行解耦,也方便后期的業(yè)務(wù)的擴(kuò)展。如新用戶注冊之后,需要發(fā)放優(yōu)惠券,此時可以在保存用戶之后,發(fā)布一個新用戶的注冊成功事件,通過監(jiān)聽該事件來實(shí)現(xiàn)發(fā)放優(yōu)惠券的功能。后期新增一個對新用戶進(jìn)行xxx功能,此時可以新寫一個監(jiān)聽注冊成功事件的監(jiān)聽器,來處理新的業(yè)務(wù)邏輯,而不需要修改之前的注冊邏輯。
注意事項(xiàng)
1、監(jiān)聽器方法中一定要try-catch異常,否則會造成發(fā)布事件(有事物的)的方法進(jìn)行回滾
2、可以使用@Order注解來控制多個監(jiān)聽器的執(zhí)行順序,@Order傳入的值越小,執(zhí)行順序越高
3、對于需要進(jìn)行事物監(jiān)聽或不想try-catch runtime異常,可以使用@TransactionalEventListener注解
@TransactionalEventListener 監(jiān)聽器
在該注解的源碼中:
* <p>If the event is not published within the boundaries of a managed transaction, the
* event is discarded unless the {@link #fallbackExecution} flag is explicitly set. If a
* transaction is running, the event is processed according to its {@code TransactionPhase}.
大意是:如果事件的發(fā)布不是在事物(@Transactional)范圍內(nèi),則監(jiān)聽不到該事件,除非將fallbackExecution標(biāo)志設(shè)置為true(@TransactionalEventListener(fallbackExecution = true));如果在事物中,可以選擇在事物的哪個階段來監(jiān)聽事件,默認(rèn)在事物提交后監(jiān)聽。
修改監(jiān)聽事物的范圍:@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
在監(jiān)聽器中重新開一個事物
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
public void listenEvent1(PersonSaveEvent<Integer> event) {
divide(event);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void divide(PersonSaveEvent<Integer> event) {
System.out.println("監(jiān)聽到PersonSaveEvent事件; 接收到的值:" + event.getData() + ";接受的時間為" + Instant.ofEpochMilli(event.getTimestamp()));
}
以上事件都是同步,如果需要異步則需要開啟異步支持,在監(jiān)聽器方法加上@Async 注解即可。
/**
* @author peter
* @version 1.0
* @date 2019/04/18 08:47
*/
@Configuration
@EnableAsync
public class AsyncEventConfiguration implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
return Executors.newCachedThreadPool();
}
}
一旦開始異步執(zhí)行,方法的異常將不會拋出,只能在方法內(nèi)部處理。如需在方法外處理異常:Async 異常處理在文章最后
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java并發(fā)編程之線程池實(shí)現(xiàn)原理詳解
池化思想是一種空間換時間的思想,期望使用預(yù)先創(chuàng)建好的對象來減少頻繁創(chuàng)建對象的性能開銷,java中有多種池化思想的應(yīng)用,例如:數(shù)據(jù)庫連接池、線程池等,下面就來具體講講2023-05-05
mybatis plus自動生成代碼tinyint(1)自動轉(zhuǎn)換為Boolean的問題及解決
這篇文章主要介紹了mybatis plus自動生成代碼tinyint(1)自動轉(zhuǎn)換為Boolean的問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
SpringBoot中忽略實(shí)體類中的某個屬性不返回給前端的方法(示例詳解)
本文介紹了在Spring Boot中使用Jackson和Fastjson忽略實(shí)體類屬性不返回給前端的方法,在Jackson中,同時使用@JsonProperty和@JsonIgnore時,@JsonIgnore可能失效,Fastjson中可以使用@JSONField(serialize=false)來實(shí)現(xiàn),本文結(jié)合實(shí)例代碼介紹的非常詳細(xì),需要的朋友參考下吧2024-11-11
使用XSD校驗(yàn)Mybatis的SqlMapper配置文件的方法(1)
這篇文章以前面對SqlSessionFactoryBean的重構(gòu)為基礎(chǔ),簡單的介紹了相關(guān)操作知識,然后在給大家分享使用XSD校驗(yàn)Mybatis的SqlMapper配置文件的方法,感興趣的朋友參考下吧2016-11-11
jsch中ChannelShell與ChannelExec的區(qū)別及說明
這篇文章主要介紹了jsch中ChannelShell與ChannelExec的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
如何讀取properties或yml文件數(shù)據(jù)并匹配
這篇文章主要介紹了如何讀取properties或yml文件數(shù)據(jù)并匹配方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12

