ApplicationContext提供事件处理通过ApplicationEvent类和ApplicationListener接口。如果一个bean在容器中实现ApplicationListener接口,每次一个ApplicationEvent被发布到ApplicationContext中,这类bean就会收到这些通知。从本质上讲,这是标准的观察者设计模式。
观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式主要有两个角色
- Subject 观察主题对象,也可以叫被观察或者被订阅对象
- Observer 观察者或者订阅者对象,当
Subject
有变动,就会通知到每一个Observer
/**
* 观察者主题对象
*/
public interface Subject {
/**
* 订阅操作
*/
void attach(Observer observer);
/**
* 取消订阅操作
*/
void detach(Observer observer);
/**
* 通知变动
*/
void notifyChanged(Object event);
}
/**
* 观察者订阅人对象
*/
public interface Observer {
/**
* 接收变动通知
*/
void update(Object event);
}
public static class RealSubject implements Subject {
private List<Observer> observerList = new ArrayList<>();
@Override
public void attach(Observer observer) {
observerList.add(observer);
}
@Override
public void detach(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyChanged(Object event) {
for (Observer observer : observerList) {
observer.update(event);
}
}
}
public static class RealObject implements Observer {
@Override
public void update(Object event) {
System.out.println("接收到了通知:"+event);
}
}
public static void main(String[] args) {
Subject subject = new RealSubject();
Observer observer = new RealObject();
subject.attach(observer);
subject.notifyChanged(new EventObject("一个事件"));
}
在Java中观察者模式被Java API java.util.Observable和java.util.Observer实现。前者可认为是数据的发布者,后者为数据的接受者。Observable和Observer的关联关系为一对多或多对多。
public static class RealSubject extends Observable {
public void makeChanged(Object event) {
setChanged();
notifyObservers(event);
}
}
public static class RealObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("调用了-->");
}
}
public static void main(String[] args) {
RealSubject subject = new RealSubject();
RealObserver observer = new RealObserver();
subject.addObserver(observer);
subject.makeChanged(new EventObject("一个事件"));
}
要点:
-
观察者模式定义了对象之间一对多的关系。
-
主题(也就是可观察者)用一个共同的接口来更新观察者
-
观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口。
-
使用此模式时,你可从被观察者处推(push)数据。
-
有多个观察者时,不可以依赖特定的通知次序。
-
Java有多种观察者模式的实现,包括了通用的java.util.Observable。
-
要注意java.util.Observable实现上所带来的一些问题。
-
如果有必要的话,可以实现自己的Observable,这并不难不要害怕。
-
Swing大量使用观察者模式, 许多GUI框架也是如此。
-
此模式也被应用在许多地方, 例如:JavaBeans、RMI。
Spring实现方式
实现Spring事件机制主要有4个类:
ApplicationEvent:事件,每个实现类表示一类事件,可携带数据。
ApplicationListener:事件监听器,用于接收事件处理时间。
ApplicationEventMulticaster:事件管理者,用于事件监听器的注册和事件的广播。
ApplicationEventPublisher:事件发布者,委托ApplicationEventMulticaster完成事件发布。
Spring中的事件:ApplicationEvent
观察者模式中传播的数据比较抽象,如Observable可发布任意的Object,而事件/监听器模式所发布的内容则有类型限制,在Java中他必须是java.util.EventObject对象,虽然在Java语言层面并无此限制,不过这是行之有年的业界规则,所以无论Java Beans还是Java AWT/Swing都遵照改规则,Spring事件自然也不会例外,所以Spring事件抽象类ApplicationEvent必然扩展EventObject。
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
EventObject并不提供默认构造器,它需要外部传递一个名为source的构造器参数用于记录并跟踪事件的来源,如Spring事件ContextRefreshedEvent,其事件源为当前ApplicationContext。
下表描述了Spring提供的标准事件:
事件 |
描述 |
---|---|
ContextRefreshedEvent | 事件发布在ApplicationContext初始化或刷新时(例如,通过在ConfigurableApplicationContext接口使用refresh()方法)。这里,“初始化”意味着所有bean加载,post-processor bean被检测到并且激活,单例预先实例化,ApplicationContext对象可以使用了。只要上下文没有关闭,可以触发多次刷新,ApplicationContext提供了一种可选择的支持这种“热”刷新。例如,XmlWebApplicationContext支持热刷新,但GenericApplicationContext并非如此。具体是在AbstractApplicationContext的finishRefresh()方法中。 |
ContextStartedEvent | 事件发布在ApplicationContext开始使用ConfigurableApp |