日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring的事件发布机制

發布時間:2025/3/20 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring的事件发布机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:Spring的事件發布

??? ApplicationContext提供了針對Bean的事件傳播功能,其中的主角是publishEvent()方法,通過這個方法可以將事件通知給系統內的監聽器(需實現ApplicationListener接口)。

??? ApplicationContext這個接口,是Spring的上下文,通常獲取Bean就需要這個接口,這個接口并不是直接繼承于BeanFactory,其中最著名的是直接繼承了ApplicationPublisher接口,這個接口查看源碼可以發現:只有一個方法,那就是主角 void publishEvent(ApplicationEvent event);

??? Spring提供的基于Aware相關的接口有ApplicationContextAware,ResourceloaderAware,ServletContextAware(注意:Struts2也有這個接口,注意區分),最常用的就這三個,而Spring的事件發布機制需要用到ApplicationContextAware接口。

??? 實現了ApplicationContextAware的Bean,在Bean初始化時將會被注入ApplicationContext實例(因為這個接口里有set(ApplictationContext ctx)方法)

二:有了以上基礎,看示例代碼:

1.首先創建事件類 TradeEvent

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 packagenet.wang.test; importorg.springframework.context.ApplicationEvent; /** ?* 事件Event ?* @author LiuRuoWang ?*/ publicclassTradeEvent extendsApplicationEvent{ ????? ????publicTradeEvent(Object source) { ????????super(source); ????????System.out.println("事件:TradeEvent event !!"); ????} ????? }
事件必須繼承Spring提供的ApplicationEvent抽象類
2.然后編寫 事件的發布者HelloWorld
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 packagenet.wang.test; importorg.springframework.context.ApplicationEventPublisher; importorg.springframework.context.ApplicationEventPublisherAware; /** ?* 事件的發布者 ?* @author LiuRuoWang ?*/ publicclassHelloWorld implementsApplicationEventPublisherAware{ ????? ????privateString word; ????? ????publicvoidsetWord(String word) { ????????this.word = word; ????} ????? ????privateApplicationEventPublisher tradeEventPublisher; ????? ????publicvoidsetApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { ????????this.tradeEventPublisher=applicationEventPublisher; ????} ????? ????publicvoidsay(){ ????????System.out.println("say:"+this.word); ????????TradeEvent tradeEvent = newTradeEvent(newString("HelloWorld!")); ????????this.tradeEventPublisher.publishEvent(tradeEvent); ????} ????? }
1 其中在say()方法里發布了事件
1 3.最后編寫 事件的接收者EventReceiver:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 packagenet.wang.test; importorg.springframework.context.ApplicationListener; /** ?* 事件的接收者 ?* @author LiuRuoWang ?*/ publicclassEventReceiver implementsApplicationListener<TradeEvent>{ ????publicvoidonApplicationEvent(TradeEvent event) { ????????System.out.println("監聽到的事件:"+event.getSource()); ????} }
1 事件的接收者其實是一個監聽器,必須實現ApplicationListener,注意把事件TradeEvent直接寫到泛型中

1 4.applicationContext.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?xml version="1.0"encoding="GBK"?> <beans ????xmlns="http://www.springframework.org/schema/beans" ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ????xmlns:p="http://www.springframework.org/schema/p" ????xmlns:aop="http://www.springframework.org/schema/aop" ????xmlns:tx="http://www.springframework.org/schema/tx" ????xsi:schemaLocation="http://www.springframework.org/schema/beans ????????http://www.springframework.org/schema/beans/spring-beans-3.1.xsd ????????http://www.springframework.org/schema/aop ????????http://www.springframework.org/schema/aop/spring-aop-3.1.xsd ????????http://www.springframework.org/schema/tx ????????http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> ????? ????<bean name="helloWrold"class="net.wang.test.HelloWorld"> ????????<property name="word"value="Word!"/> ????</bean> ????? ????<bean name="eventReceiver"class="net.wang.test.EventReceiver"/> ????? </beans>

注意把事件的接收者寫入配置文件中

5.測試Test:

1 2 3 4 5 6 7 8 9 10 11 12 packagenet.wang.test; importorg.springframework.context.ApplicationContext; importorg.springframework.context.support.ClassPathXmlApplicationContext; publicclassTest { ????publicstaticvoidmain(String[] args) { ????????ApplicationContext ctx=newClassPathXmlApplicationContext("applicationContext.xml"); ????????HelloWorld h = (HelloWorld) ctx.getBean("helloWrold"); ????????h.say(); ????} }

6.結果顯示:

結果中已經顯示監聽到的事件,說明成功。




Spring 中的事件監聽的實現

這里我們不討論事件監聽的機制的原理,我們只討論如何在項目中實現時間監聽。?
Spring的事件監聽是基于觀察者模式。設計開發中。如下類與接口是我們必須要使用的。

ApplicationContext

首先我們了解一下ApplicationContext,還記得

ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
  • 1

ApplicationContext相當于Spring的一個與IOC容器連接的橋梁,通過getBean();方法,我們可以輕松的從IOC容器中獲取Bean對象。?
因為ApplicationContext是實現ApplicationEventPublisher的。查看ApplicationEventPublisher的源碼,我們發現有一方法publishEvent。此方法便是發布事件的方法,即觸發事件的方法,通過調用publishEvent方法,注入事件ApplicationEvent的子類,實現事件的觸發。

//這個是ApplicationContext類的聲明 public interface ApplicationContext extends EnvironmentCapable,ListableBeanFactory,HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {//...}
  • 1
  • 2
//ApplicationEventPublisher源碼 public interface ApplicationEventPublisher {//該類只有這一個方法,用于發布通知,需要事件作為參數void publishEvent(ApplicationEvent event);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

說了一大堆,就是想說ApplicationContext的

publicEvent(ApplicationEvent event);

方法是可以用來發布通知,相當于觸發事件的事件源。

ApplicationContextAware

ApplicationContextAware類似于ServeletRequestAware,通過讓Action實現Aware,使得Action初始化之后便可以獲得一些資源,這里我們讓Action實現ApplicationContext,使得Action擁有ApplicationContext,Action中擁有ApplicationContext之后就可以調用publicEvent方法進行通知

public interface ApplicationContextAware extends Aware {void setApplicationContext(ApplicationContext applicationContext) throws BeansException;}
  • 1
  • 2
  • 3
  • 4

ApplicationEvent

ApplicationEvent相當于一個事件,所有自定義事件都需要繼承這個抽象類。在Eclipse中Ctrl+Shift+H調用類的層次結構列表,可以看到如下?
?
Application下抽象子類ApplicationContextEvent的下面有4個已經實現好的事件?
ContextClosedEvent(容器關閉時)?
ContextRefreshedEvent(容器刷新是)?
ContextStartedEvent(容器啟動時候)?
ContextStoppedEvent(容器停止的時候)?
同樣,這四個事件都繼承了ApplicationEvent,如果我們想自定義事件,也可以通過繼承ApplicationEvent來實現?
嗯,同樣是一句話總結ApplicationEvent就是一個抽象類,創建時間的時候只需要繼承它就可以。

ApplicationListener

從名字可以看出來,這是一個監聽器。為什么需要監聽器呢?監聽器是用于接收事件,并觸發事件的操作,這樣說起來可能有點費解,簡單的說就是,Listener是監聽ApplicationContext.publishEvent,方法的調用,一旦調用publishEvent,就會執行ApplicaitonListener中的方法,下面這個是ApplicationContext的源碼。

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {/*** publishEvent觸發該方方法* 可以在該方法中寫各種業務邏輯*/void onApplicationEvent(E event);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

這里是實際代碼實現的過程

  • 新建一個MyEvent的類,繼承ApplicationEvent抽象類
  • package cn.blueboz.elec.event;import org.springframework.context.ApplicationEvent;public class MyEvent extends ApplicationEvent {//存放構造器送入的值private String msg;//構造器參數可以隨意設置,這里為了方便調試,設置為字符串public MyEvent(String msg) {super(msg);this.msg=msg;}//自定義一個方法,這個方法也可以隨意寫,這里也是測試用public void myevent(){System.out.println("********My event**************");System.out.println(msg);System.out.println("*******************************");} }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.新建一個監聽器MyListener

    package cn.blueboz.elec.listener;import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextStartedEvent; import org.springframework.context.event.ContextStoppedEvent; import org.springframework.stereotype.Service;import cn.blueboz.elec.event.HisEvent; import cn.blueboz.elec.event.MyEvent;//注入IOC容器中 @Service("myListener") public class MyListener implements ApplicationListener<ApplicationEvent> {//調用ApplicationContext.publishEvent方法時會觸發執行該方法@Overridepublic void onApplicationEvent(ApplicationEvent event) {//判斷事件為MyEvent時候執行if(event instanceof MyEvent){//強制轉換MyEvent evt=(MyEvent) event;//執行自定義事件中的自定義方法evt.myevent();}//如果容器關閉時,觸發if(event instanceof ContextClosedEvent){ContextClosedEvent cce=(ContextClosedEvent) event;System.out.println("#####################");System.out.println("容器關閉");System.out.println(cce);System.out.println("#####################");}//容器刷新時候觸發if(event instanceof ContextRefreshedEvent){ContextRefreshedEvent cre=(ContextRefreshedEvent) event;System.out.println("#####################");System.out.println("容器刷新");System.out.println(cre);System.out.println("#####################");}//容器啟動的時候觸發if(event instanceof ContextStartedEvent){ContextStartedEvent cse=(ContextStartedEvent) event;System.out.println("#####################");System.out.println("容器啟動");System.out.println(cse);System.out.println("#####################");}//容器停止時候觸發if(event instanceof ContextStoppedEvent){ContextStoppedEvent cse=(ContextStoppedEvent) event;System.out.println("#####################");System.out.println("容器停止");System.out.println(cse);System.out.println("#####################");}}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    3.最后,我們要再Action中發布通知publishEvent;

    package cn.blueboz.elec.web.action;import javax.annotation.Resource;import org.apache.struts2.interceptor.ServletRequestAware; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Scope; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Controller;import cn.blueboz.elec.domain.ElecText; import cn.blueboz.elec.event.MyEvent; import cn.blueboz.elec.service.IElecTextService;//指定為prototype原型,對應每一個請求都會產生一個實例對象 @Controller("elecTextAction") @Scope(value="prototype") public class ElecTextAction extends BaseAction<ElecText> implements ApplicationContextAware,ServletRequestAware {//首先獲得模型驅動對象ElecText elecText=getModel();protected ApplicationContext applicationContext;//注入Service指定從Spring的IOC容器中注入的對象的名稱@Resource(name=IElecTextService.SERVICE_NAME)private IElecTextService elecTextService;public String save(){//從表單中傳送過來的實例對象elecTextService.saveElecText(elecText);/*** 請關注這一行代碼,在頁面中訪問時候調用save方法* save方法中執行了publishEvent方法發布通知。* 傳入參數是自定義事件MyEvent*/applicationContext.publishEvent(new MyEvent("在Action中的save方法Public了Event"));return "save";}@Overridepublic void setApplicationContext(ApplicationContext applicationContext)throws BeansException {this.applicationContext=applicationContext;} }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    4.啟動Tomcat時候命令行輸出

    ##################### 容器刷新 org.springframework.context.event.ContextRefreshedEvent[source=Root WebApplicationContext: startup date [Fri Nov 20 17:12:47 CST 2015]; root of context hierarchy] #####################
    • 1
    • 2
    • 3
    • 4

    訪問頁面的時候,命令行輸出,可以看出,觸發了MyEvent方法輸出。

    ********My event************** 在Action中的save方法Public了Event *******************************

    總結

    以上是生活随笔為你收集整理的Spring的事件发布机制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。