javascript
java观察者模式在spring中的应用_Spring源码之spring中的观察者模式和监听器的使用...
聲明:本文根據(jù)魯班學(xué)院子路老師spring中觀察者模式課程整理得來
觀察者模式特點:
被觀察者持有監(jiān)聽的觀察者的引用。
被觀察者支持增加和刪除的觀察者。
被觀察者狀態(tài)改變通知觀察者。
JDK中觀察者implements Observer接口,重寫update()方法
當觀察者發(fā)生變化,收到通知進行具體的處理
可以隨時取消
松耦合:
觀察者增加或者刪除無需修改被觀察者的代碼,只需調(diào)用被觀察者對應(yīng)的增加或則刪除的方法即可
被觀察者只負責(zé)通知觀察者,但無需了解觀察者如何處理通知
觀察者只需等待被觀察者通知,無需觀察被觀察者細節(jié)
通知不會錯過:
由于被動接受,正常情況下不會錯過主體的改變通知,而主動獲取的話,由于時機選擇問題,可能導(dǎo)致錯過某些狀態(tài)
Java實現(xiàn)
Java中有觀察者模式使用的API
Java.util.Observable 這是一個類
java.util.Observer 這是一個接口
開關(guān)的重要性
可以篩選通知
可以撤銷通知
可以控制通知
Spring中的觀察者模式
在Spring中定義和應(yīng)用程序上下文相關(guān)的事件時需要繼承ApplicationEvent類
public abstract class ApplicationEvent extendsEventObject {/**use serialVersionUID from Spring 1.2 for interoperability.*/
private static final long serialVersionUID = 7099057708183571937L;/**System time when the event happened.*/
private final longtimestamp;/*** Create a new {@codeApplicationEvent}.
*@paramsource the object on which the event initially occurred or with
* which the event is associated (never {@codenull})*/
publicApplicationEvent(Object source) {super(source);this.timestamp =System.currentTimeMillis();
}/*** Return the system time in milliseconds when the event occurred.*/
public final longgetTimestamp() {return this.timestamp;
}
}
在ApplicationEvent的父類EventObject類(這個是java源碼中的類)中有一個得到事件源的方法getSource()
Spring中的Events
事件通過**org.springframework.context.ApplicationEvent**實例來表示。這個抽象類繼承擴展了**java.util.EventObject**,可以使用**EventObject中的getSource**方法,我們可以很容易地獲得所發(fā)生的給定事件的對象。這里,事件存在兩種類型。
1. **與應(yīng)用程序上下文相關(guān)聯(lián)**
所有這種類型的事件都繼承自**org.springframework.context.event.ApplicationContextEvent**類。
它們應(yīng)用于由**org.springframework.context.ApplicationContext**引發(fā)的事件(其構(gòu)造函數(shù)傳入的是`ApplicationContext`類型的參數(shù))。
這樣,我們就可以直接通過應(yīng)用程序上下文的生命周期來得到所發(fā)生的事件:`ContextStartedEvent`在上下文啟動時被啟動,當它停止時啟動`ContextStoppedEvent`,當上下文被刷新時產(chǎn)生`ContextRefreshedEvent`,最后在上下文關(guān)閉時產(chǎn)生`ContextClosedEvent`。
以ContextStartedEvent這個類為例,實現(xiàn)SpringEvent的擴展功能,這個事件在context.start()的時候來進行監(jiān)聽處理。
public class ContextStartedEvent extendsApplicationContextEvent {/*** Create a new ContextStartedEvent.
*@paramsource the {@codeApplicationContext} that has been started
* (must not be {@codenull})*/
publicContextStartedEvent(ApplicationContext source) {super(source);
}
}
1.首先創(chuàng)建一個listener類
/*** spring通過實現(xiàn)ApplicationListener這個接口,同時傳入一個泛型(ContextStartedEvent)就可以
* 監(jiān)聽到這個泛型對應(yīng)的事件*/@Componentpublic class SpringListenerStart implements ApplicationListener{
@Overridepublic voidonApplicationEvent(ContextStartedEvent event) {
System.out.println("----- spring application start listener------");
}
}
2.創(chuàng)建測試類
public classTest {public static voidmain(String[] args) {
AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(WkApplication.class);
context.start();//在調(diào)用context的start()方法時,會觸發(fā)spring的監(jiān)聽器,調(diào)用ContextStartedEvent對應(yīng)的事件方法
}
}
3.運行結(jié)果
Spring監(jiān)聽器的應(yīng)用(模擬一個發(fā)郵件的監(jiān)聽器):
1.創(chuàng)建一個SpringMailEvent類,使它繼承ApplicationEvent類(這個是Spring的事件類,自己的事件都要繼承它)
public class SpringMailEvent extends ApplicationEvent implementsSerializable {//需要序列化,要不會報錯。我也不知道為什么
private static final long serialVersionUID=762508508425139227l;privateString content;/*** Create a new {@codeApplicationEvent}.
*
*@paramsource the object on which the event initially occurred or with
* which the event is associated (never {@codenull})*/
publicSpringMailEvent(Object source) {super(source);
}publicString getContent() {returncontent;
}public voidsetContent(String content) {this.content =content;
}
}
2.創(chuàng)建一個SpringMailListener監(jiān)聽器類,使他實現(xiàn)ApplicationListener接口,同時泛型中穿我們自己定義的事件
@Componentpublic class SpringMailListener implements ApplicationListener{/*** 當程序調(diào)用了一個發(fā)郵件的方法時,這個監(jiān)聽器就會監(jiān)聽到,
* 同時在onApplicationEvent方法中做出響應(yīng)
*@paramevent the event to respond to*/@Overridepublic voidonApplicationEvent(SpringMailEvent event) {
System.out.println("mail send ");
}
}
3.創(chuàng)建一個類,使自定義的監(jiān)聽器和事件與spring容器關(guān)聯(lián)起來
/*** 創(chuàng)建自己的類,使自定義的監(jiān)聽器和事件與spring容器關(guān)聯(lián)起來*/@Componentpublic classMailBean {
@Autowired
ApplicationContext context;//注入Sprig應(yīng)用程序上下文/*** 我們之前只是定義了SpringMailEvent類,但是這個類并沒有和Spring容器關(guān)聯(lián)起來,
* 所以我們需要借助ApplicationContext的publishEvent()方法,把這個事件發(fā)布出去*/
public voidsendMail(){
context.publishEvent(newSpringMailEvent(context));
}
}
4.測試類
public classTest {public static voidmain(String[] args) {
AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(WkApplication.class);//context.start();//觸發(fā)發(fā)郵件的事件
context.getBean(MailBean.class).sendMail();
}
}
5.測試結(jié)果
2. **與request 請求相關(guān)聯(lián)**
由**org.springframework.web.context.support.RequestHandledEvent**實例來表示,當在ApplicationContext中處理請求時,它們被引發(fā)。
Spring如何將事件分配給專門的監(jiān)聽器?
這個過程由事件廣播器來實現(xiàn),由**org.springframework.context.event.ApplicationEventMulticaster**接口的實現(xiàn)表示。此接口定義了3種方法
1. **addApplicationListener()** ?添加新的監(jiān)聽器**:定義了兩種方法來添加新的監(jiān)聽器:**addApplicationListener(ApplicationListener> listener)**和**addApplicationListenerBean(String listenerBeanName)**。當監(jiān)聽器對象已知時,可以應(yīng)用第一個。如果使用第二個,我們需要將bean name 得到listener對象(`依賴查找DL`),然后再將其添加到`listener`列表中
2. **removeApplicationListenerBean(String listenerBeanName)** **刪除監(jiān)聽器**:添加方法一樣,我們可以通過傳遞對象來刪除一個監(jiān)聽器(**removeApplicationListener(ApplicationListener> listener)**或通過傳遞bean名稱。第三種方法,**removeAllListeners()**用來刪除所有已注冊的監(jiān)聽器。
3. **multicastEvent(ApplicationEvent event)****將事件發(fā)送到已注冊的監(jiān)聽器**。
總結(jié)
以上是生活随笔為你收集整理的java观察者模式在spring中的应用_Spring源码之spring中的观察者模式和监听器的使用...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: wstring 截取_StringUti
 - 下一篇: java如何显示当天世界_Java学习笔