Spring事件監(jiān)聽基本原理與使用詳解
一、簡介
1、Spring事件監(jiān)聽基本原理
Spring的事件監(jiān)聽機(jī)制和發(fā)布訂閱機(jī)制是很相似的:發(fā)布了一個(gè)事件后,監(jiān)聽該類型事件的所有監(jiān)聽器會(huì)觸發(fā)相應(yīng)的處理邏輯。
正如Spring官方文檔上所說的,整個(gè)上就是一個(gè)觀察者的模式。那么,我們不妨猜測下,Spring是如何來實(shí)現(xiàn)事件發(fā)布監(jiān)聽的:底層使用一個(gè)集合存儲(chǔ)了所有的監(jiān)聽器,當(dāng)發(fā)布了一個(gè)事件后,遍歷事件監(jiān)聽器集合,然后過濾符合事件類型的監(jiān)聽器,最后觸發(fā)相應(yīng)的事件處理邏輯。
2、Spring中事件監(jiān)聽的相關(guān)規(guī)范
在Spring中,事件監(jiān)聽機(jī)制主要涉及到了一下幾個(gè)關(guān)鍵的規(guī)范(抽象類及接口):ApplicationEvent、ApplicationListener、ApplicationEventPublisher
- ApplicationEvent: Spring的事件是符合jdk的規(guī)范的,這個(gè)抽象類繼承了jdk內(nèi)置的事件規(guī)范類EventObject(即jdk建議所有的事件都繼承EventObject這個(gè)類)。ApplicationEvent是Spring家的事件規(guī)范。所以我們在自定義事件的時(shí)候,可以繼承與ApplicationEvent,比如,Spring家自己關(guān)于容器上下文事件就又定義了一個(gè)容器上下文的時(shí)間規(guī)范ApplicationContextEvent,它同樣是繼承于ApplicationEvent的,只不過擴(kuò)充了獲取發(fā)出事件容器的方法;今后,我們同樣可以在繼承于ApplicationEvent的基礎(chǔ)上定義自己的事件規(guī)范。
- ApplicationListener:這是一個(gè)函數(shù)式接口,同樣時(shí)事件監(jiān)聽器的規(guī)范,當(dāng)監(jiān)聽到自己監(jiān)聽的事件類型時(shí)就會(huì)調(diào)用onApplicationEvent方法來執(zhí)行監(jiān)聽邏輯
- ApplicationEventPublisher:這同樣是一個(gè)函數(shù)式接口,定義了事件發(fā)布的規(guī)范,任何的事件發(fā)布器ApplicationEventPublisher都是通過調(diào)用publishEvent來進(jìn)行事件的發(fā)布
二、Spring事件監(jiān)聽器的使用
1、自定義事件創(chuàng)建
在Spring中,所有的事件需要繼承自ApplicationEvent,自定義事件的不同可以監(jiān)聽多個(gè),一個(gè)最基礎(chǔ)的MsgEvent如下
public class MyEvent extends ApplicationEvent {
private String msg;
// 必須繼承實(shí)現(xiàn)
public MyEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
@Override
public String toString() {
return "MyEvent{" +
"msg='" + msg + '\'' +
'}';
}
}2、自定義監(jiān)聽器
2.1 方法介紹
springboot進(jìn)行事件監(jiān)聽有四種方式,選擇任意一種即可
- 將監(jiān)聽器裝載入spring容器(常用)
- 通過@EventListener注解實(shí)現(xiàn)事件監(jiān)聽(常用)
- 手工向ApplicationContext中添加監(jiān)聽器
- 在application.properties中配置監(jiān)聽器
2.2 將監(jiān)聽器裝載入spring容器
// 裝載入spring容器中
@Slf4j
@Component
public class MyListener1 implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
// 這里可以自定義自己的方法
log.info(String.format("%s監(jiān)聽到事件源:%s.", MyListener1.class.getName(), event.toString()));
}
}如果不加@Component注解加入Spring容器,也可以手動(dòng)加入
@SpringBootApplication
public class ListenerApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ListenerApplication.class, args);
//裝載監(jiān)聽
context.addApplicationListener(new MyListener1());
}
}也可以通過配置文application.properties中配置監(jiān)聽器:context.listener.classes=com.listener.MyListener1
2.3 @EventListener注解實(shí)現(xiàn)事件監(jiān)聽
@Component
@Slf4j
public class MyListener2{
// 通過注解的方法
@EventListener(MyEvent.class)
public void consumer(MyEvent msgEvent) {
log.info(String.format("%s監(jiān)聽到事件源:%s.", MsgPublisher.class.getName(), msgEvent.toString()));
}
}3、事件發(fā)布
前面是消費(fèi)事件,消費(fèi)的前提是有事件產(chǎn)生,在Spring中,發(fā)布事件主要需要借助ApplicationContext來實(shí)現(xiàn)
@Component
@Slf4j
public class MsgPublisher implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
// 發(fā)起事件通知
public void publish(String msg) {
applicationContext.publishEvent(new MyEvent1(this, msg));
}
// 通過注解的方法
@EventListener(MyEvent.class)
public void consumer(MyEvent msgEvent) {
log.info(String.format("%s監(jiān)聽到事件源:%s.", MsgPublisher.class.getName(), msgEvent.toString()));
}
/**
* 這個(gè)只是測試,到時(shí)候spring直接調(diào)用即可
*/
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MsgPublisher.class);
MsgPublisher msgPublisher = context.getBean(MsgPublisher.class);
msgPublisher.publish("hello world");
}
}到此這篇關(guān)于Spring事件監(jiān)聽基本原理與使用詳解的文章就介紹到這了,更多相關(guān)Spring事件監(jiān)聽內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
教你怎么用java一鍵自動(dòng)生成數(shù)據(jù)庫文檔
最近小編也在找這樣的插件,就是不想寫文檔了,浪費(fèi)時(shí)間和心情啊,果然我找到一款比較好用,操作簡單不復(fù)雜.screw 是一個(gè)簡潔好用的數(shù)據(jù)庫表結(jié)構(gòu)文檔的生成工具,支持 MySQL、Oracle、PostgreSQL 等主流的關(guān)系數(shù)據(jù)庫.需要的朋友可以參考下2021-05-05
Mybatis-Plus save和saveBatch方法忽略自增主鍵詳解
Mybatis-Plus在從3.4.0升級(jí)到3.5.6后,save和saveBatch方法在處理自增主鍵時(shí)會(huì)出現(xiàn)主鍵沖突的問題,這是因?yàn)?.5.6版本中增加了`ignoreAutoIncrementColumn`屬性,默認(rèn)值為false,導(dǎo)致在生成SQL語句時(shí)忽略了自增主鍵,解決方法是手動(dòng)設(shè)置主鍵值2025-12-12
Spring MVC實(shí)現(xiàn)mysql數(shù)據(jù)庫增刪改查完整實(shí)例
這篇文章主要介紹了Spring MVC實(shí)現(xiàn)mysql數(shù)據(jù)庫增刪改查完整實(shí)例,從創(chuàng)建一個(gè)web項(xiàng)目開始,分享了項(xiàng)目結(jié)構(gòu)以及具體Java代碼和前端頁面等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以了解下。2017-12-12
SpringBoot3集成iText實(shí)現(xiàn)PDF導(dǎo)出功能
不知道小伙伴們在項(xiàng)目中有沒有遇到過導(dǎo)出 PDF 的需求,小編在之前的 tienchin 項(xiàng)目中有一個(gè)合同導(dǎo)出的功能,需要將文檔導(dǎo)出為PDF,將文檔導(dǎo)出為 PDF 有很多方案,不同方案的優(yōu)缺點(diǎn)也各不相同,今天小編就和大家演示一個(gè),感興趣的小伙伴跟著小編一起來看看吧2024-10-10
spring三級(jí)緩存以及為什么不用二級(jí)緩存解讀
Spring三級(jí)緩存機(jī)制解決了循環(huán)依賴問題,通過一級(jí)緩存存放完全初始化的bean,二級(jí)緩存存放實(shí)例化但未完成依賴注入和初始化的bean,三級(jí)緩存存放bean的創(chuàng)建工廠,避免了重復(fù)創(chuàng)建和確保代理對象的正確生成2025-02-02
SpringBoot里使用Servlet進(jìn)行請求的實(shí)現(xiàn)示例
這篇文章主要介紹了SpringBoot里使用Servlet進(jìn)行請求的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Java中的數(shù)組流ByteArrayOutputStream用法
Java中的ByteArrayOutputStream是java.io包中的一個(gè)類,用于在內(nèi)存中創(chuàng)建字節(jié)數(shù)組緩沖區(qū),支持動(dòng)態(tài)擴(kuò)展,它繼承自O(shè)utputStream,允許以字節(jié)形式寫入數(shù)據(jù),無需與外部設(shè)備交互,常用方法包括write()、toByteArray()、toString()等2024-09-09

