本篇博客我們就來(lái)聊一下Spring框架中的觀察者模式的應(yīng)用,即事件的發(fā)送與監(jiān)聽(tīng)機(jī)制。之前我們已經(jīng)剖析過(guò)觀察者模式的具體實(shí)現(xiàn),以及使用Swift3.0自定義過(guò)通知機(jī)制。所以本篇博客對(duì)于事件發(fā)送與監(jiān)聽(tīng)的底層實(shí)現(xiàn)就不做過(guò)多贅述了。下方會(huì)給出Spring中是如何進(jìn)行事件的發(fā)送與監(jiān)聽(tīng)的。聊完事件的發(fā)送與監(jiān)聽(tīng),我們?cè)賮?lái)聊一下如何使用@Profile注解來(lái)切換“生產(chǎn)環(huán)境”與“開(kāi)發(fā)環(huán)境”。

 

一、Spring中的事件發(fā)送與監(jiān)聽(tīng)

Spring中的事件發(fā)送與監(jiān)聽(tīng)說(shuō)白了就是廣播。由Publisher來(lái)發(fā)送Event,有Listener來(lái)接收Event。Publisher和Listenter一對(duì)多的關(guān)系,當(dāng)Publisher在發(fā)送Event時(shí),并不確定是哪些Listener會(huì)收到該發(fā)布的事件。當(dāng)然再進(jìn)一步說(shuō),Spring的事件發(fā)送與監(jiān)聽(tīng)的本質(zhì)還是觀察者模式的具體實(shí)現(xiàn)。之前的博客我們拿Swift語(yǔ)言來(lái)具體的實(shí)現(xiàn)和分析了觀察者模式,關(guān)于觀察者模式的具體內(nèi)容,請(qǐng)移步于《自己動(dòng)手使用“觀察者模式”實(shí)現(xiàn)通知機(jī)制》。

該部分關(guān)于“觀察者模式”的東西就不做過(guò)多贅述了,主要就來(lái)看一下在Spring中是如何使用事件發(fā)送以及事件監(jiān)聽(tīng)的。

 

1、事件發(fā)送與監(jiān)聽(tīng)的原理圖

一直看代碼比較枯燥,那么我們就來(lái)一張?jiān)韴D來(lái)看一下Spring框架中的事件發(fā)布者(Publisher)、事件(Event)、監(jiān)聽(tīng)者(Listener)之間的關(guān)系。上面也提到了,Publisher與Listener之間的關(guān)系是一對(duì)多的關(guān)系。也就是說(shuō)Publisher發(fā)布Event是通過(guò)廣播的形式來(lái)實(shí)現(xiàn)的。Publisher在發(fā)送Event時(shí),并不確定是那些Listener接收的Event。

而Event就是發(fā)送消息的載體。也就是說(shuō)Publisher與Listener之間交流的載體就是Event對(duì)象。Publisher發(fā)布Event對(duì)象,而Listener則接收Event對(duì)象。三者之間的關(guān)系具體如下所示:

移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

 

2、事件發(fā)送與監(jiān)聽(tīng)的具體實(shí)現(xiàn)

搞明白上述原理,在給出具體實(shí)現(xiàn)就簡(jiǎn)單多了。接下來(lái)我們就來(lái)看看Spring中是如何來(lái)實(shí)現(xiàn)上述關(guān)系的。

(1)、創(chuàng)建Event

因?yàn)?span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);">Event是廣播信息的載體,類(lèi)似于iOS開(kāi)發(fā)中的NSNotification。所以我們就先創(chuàng)建Spring框架中的Event。下方的DemoEvent就是我們創(chuàng)建的事件,當(dāng)然該事件要繼承ApplicationEvent類(lèi)。DemoEvent類(lèi)中的msg屬性就用來(lái)承載該事件的信息。而serialVersionUID則表示該事件的標(biāo)示。具體如下所示:

  移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

(2)、創(chuàng)建Publisher

創(chuàng)建完事件后,接下來(lái)我們就來(lái)創(chuàng)建事件的發(fā)布者。下方的DemoPublisher就是我們創(chuàng)建的發(fā)布事件的類(lèi)。在類(lèi)中我們使用@Autowired注解了ApplicationContext類(lèi)的注入點(diǎn)。因?yàn)槲覀円褂?span style="margin: 0px; padding: 0px; color: rgb(255, 0, 0);">ApplicationContext對(duì)象的publicEvent()方法來(lái)進(jìn)行推送,而publicEvent()方法的參數(shù)就是我們上面創(chuàng)建DemoEvent事件的對(duì)象。如下所示。

  移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

(3)、創(chuàng)建Listener

Event以及Publisher創(chuàng)建完畢后,接下來(lái)我們就來(lái)創(chuàng)建接收事件的Listener。我們可以創(chuàng)建多個(gè)Listener來(lái)接收Publisher發(fā)布的Event,下方就我們就以DemoListener為例。DemoListener類(lèi)實(shí)現(xiàn)了ApplicationListener接口,并且給出了onApplicationEvent()方法的實(shí)現(xiàn)。當(dāng)收到Publisher發(fā)布的Event時(shí),就會(huì)執(zhí)行下方的onApplicationEvent()方法,而該方法的參數(shù)就是我們創(chuàng)建的DemoEvent事件對(duì)象。

由下方截圖不難看出,此處我們創(chuàng)建了兩個(gè)Listener,當(dāng)上面的Publisher發(fā)布完事件后,這兩個(gè)Listener都會(huì)收到相應(yīng)的事件消息。

  移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

(4)、運(yùn)行并輸出結(jié)果

Event、Publisher、Listener創(chuàng)建完畢后,接下來(lái)我們就該測(cè)試這三者了。因?yàn)槲覀兯鶆?chuàng)建的Publisher是Spring管理的Bean(@Component),所以從Spring的容器中獲取Publisher的對(duì)象,然后調(diào)用public()方法進(jìn)行事件的發(fā)布。

下方就是我們測(cè)試用的Main方法,然后是消息的輸出。可見(jiàn),我們的這個(gè)事件的兩個(gè)監(jiān)聽(tīng)者都收到了來(lái)著Publisher的Even。

  移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

 

二、@Profile注解

在Spring框架中,我們可以使用@Profile注解來(lái)設(shè)置相應(yīng)的開(kāi)發(fā)環(huán)境,如生產(chǎn)環(huán)境、準(zhǔn)生產(chǎn)環(huán)境或者測(cè)試環(huán)境等。接下來(lái)我們就來(lái)看一下@Profile注解的使用方式。當(dāng)然@Profile注解是在Java配置類(lèi)中聲明Bean時(shí)使用的,下方會(huì)給出具體實(shí)現(xiàn)。

首先我們創(chuàng)建一個(gè)測(cè)試Bean,我們將該Bean命名為DemoProfileBean。稍后,我們將會(huì)在Java的配置文件中對(duì)該類(lèi)進(jìn)行Bean的聲明。下方代碼段比較簡(jiǎn)單,在此就不做過(guò)多贅述了。

  移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

然后我們就要來(lái)實(shí)現(xiàn)我們的Java配置類(lèi)了。下方的ProfileConfig就是該部分創(chuàng)建的Java配置文件,在其中我們聲明了兩個(gè)Bean。這兩個(gè)Bean都是DemoProfileBean類(lèi)的Bean的聲明。不過(guò)創(chuàng)建對(duì)象時(shí)所提供的參數(shù)不同。我們使用@Profile來(lái)進(jìn)行區(qū)分,如果@Profile的參數(shù)是“develop”,那么我們就將DemoProfileBean對(duì)象的參數(shù)設(shè)置成開(kāi)發(fā)環(huán)境的IP地址,如果@Profile的參數(shù)是“product”的話,那么所創(chuàng)建的DemoProfileBean的對(duì)象的參數(shù)就是生產(chǎn)環(huán)境的IP地址,具體代碼如下所示。

  移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

創(chuàng)建好上述配置文件后,接下來(lái)我們就該創(chuàng)建測(cè)試用的Main函數(shù)了。下方就是Main函數(shù)的具體內(nèi)容,下方緊接著是運(yùn)行效果。可以看出,我們指定的Profile的值不同,所創(chuàng)建的對(duì)象的參數(shù)也是不同的。具體如所示:

  移動(dòng)開(kāi)發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開(kāi)發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)