springboot的事件監(jiān)聽(tīng):為bean之間的消息通信提供支持骑歹。當(dāng)一個(gè)bean做完一件事以后,通知另一個(gè)bean知曉并做出相應(yīng)處理。這時(shí)负懦,我們需要另一個(gè)bean,監(jiān)聽(tīng)當(dāng)前bean所發(fā)生的事件柏腻。
實(shí)現(xiàn)步驟:四個(gè)步驟纸厉,五種方式
第一種方式
1、自定義事件五嫂,一般是繼承ApplicationEvent抽象類(lèi)
2颗品、定義事件監(jiān)聽(tīng)器,一般是實(shí)現(xiàn)ApplicationListener接口
3沃缘、 1)把監(jiān)聽(tīng)器加入到SpringApplication中:ApplicationListener.addListener();然后發(fā)布事件
2)或放置到spring容器:@Conponent
3)或在application.properties配置文件中配置context.listener.classes=監(jiān)聽(tīng)器全類(lèi)名
4)或在META-INF/spring.factories配置文件中配置org.springframework.context.ApplicationListener=監(jiān)聽(tīng)器全類(lèi)名
5)或編寫(xiě)一個(gè)類(lèi)躯枢,納入spring容器中,編寫(xiě)一個(gè)帶參的方法槐臀,參數(shù)為事件的父類(lèi)或需要監(jiān)聽(tīng)的事件锄蹂,加上@EventListener
3、發(fā)布事件
第一步:自定義事件水慨,繼承ApplicationEvent抽象類(lèi)
public class MyApplicationEvent extends ApplicationEvent {
public MyApplicationEvent(Object source) {
super(source);
}
}
第二步:自定義事件監(jiān)聽(tīng)器得糜,實(shí)現(xiàn)ApplicationListener接口
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
@Override
public void onApplicationEvent(MyApplicationEvent myApplicationEvent) {
System.out.println(myApplicationEvent.getClass().getName() + "被監(jiān)聽(tīng)......");
}
}
第三、四步:把監(jiān)聽(tīng)器加入spring中晰洒,然后發(fā)布事件
@SpringBootApplication
public class BlogApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(BlogApplication.class, args);
//把監(jiān)聽(tīng)器加入到SpringApplication中
context.addApplicationListener(new MyApplicationListener());
//發(fā)布事件
context.publishEvent(new MyApplicationEvent(new Object()));
context.close();
}
}
第二種方式:換一種方式將監(jiān)聽(tīng)器加入spring容器中(只需修改BlogApplication)
第三種方式:在application.properties配置文件中配置context.listener.classes=監(jiān)聽(tīng)器全類(lèi)名
第四種方式:在META-INF/spring.factories配置文件中配置org.springframework.context.ApplicationListener=監(jiān)聽(tīng)器全類(lèi)名
第五種方式:編寫(xiě)一個(gè)類(lèi)MyEventHandler,替代上文中的MyApplicationListener欢顷,將其納入spring容器中,編寫(xiě)一個(gè)帶參的方法捉蚤,參數(shù)為需要監(jiān)聽(tīng)的事件的父類(lèi)或需要監(jiān)聽(tīng)的事件抬驴,加上@EventListener。(參數(shù)的范圍越廣泛缆巧,監(jiān)聽(tīng)到的事件越多)
實(shí)現(xiàn)原理
第三種方式:配置application.properties的方式的實(shí)現(xiàn)原理布持,
參照DelegatingApplicationListener.class
的源碼:
我們發(fā)現(xiàn)這個(gè)類(lèi)中申明了一個(gè)常量
PROPERTY_NAME = "context.listener.classes"
,接著往下看onApplicationEvent
方法陕悬,源碼作者首先從application.properties配置文件中讀取到以"context.listener.classes"
為key的Listener全類(lèi)名题暖,通過(guò)ClassLoader
把他們實(shí)例化成Listener對(duì)象,繼而存入一個(gè)List<ApplicationListener<ApplicationEvent>> listeners
集合中,最后將他們排序后將他們挨個(gè)加入事件廣播中胧卤。有興趣的讀者可以結(jié)合我的解析閱讀以下源碼唯绍!
實(shí)際工作如何使用
上文我們說(shuō)到了如何定義一個(gè)事件和監(jiān)聽(tīng)器,那在工作中枝誊,如果我們要使用事件為我們達(dá)到一些目的况芒,難道需要實(shí)現(xiàn)這么麻煩的過(guò)程嘛?答案是no叶撒!spring和springboot已經(jīng)給我們編寫(xiě)好了豐富的事件供我們使用绝骚。
我們這里做一個(gè)簡(jiǎn)單的小范例,監(jiān)聽(tīng)一個(gè)ContextClosedEvent
事件祠够。
編寫(xiě)監(jiān)聽(tīng)器
@Component
public class ContextClosedEventHandler {
@EventListener
public void listener(ContextClosedEvent event) {
System.out.println("spring context stop...." + event.getClass().getName());
}
}
編寫(xiě)B(tài)logApplication
@SpringBootApplication
public class BlogApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(BlogApplication.class, args);
context.close();
}
}
至此压汪,springboot的五種事件監(jiān)聽(tīng)方式就介紹完畢啦~,如果有對(duì)springboot非常感興趣的讀者古瓤,可以關(guān)注我的springboot系列博客止剖,里面有更多的干貨分享給大家!