Spring 事件機制是觀察者模式的典型應(yīng)用饭寺,本文將由淺入深從觀察者模式傅事、java事件機制、Spring事件機制三個部分來進行分析宪郊。
-
觀察者模式
觀察者模式是軟件設(shè)計中常用的設(shè)計模式之一掂恕。定義對象間的一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象弛槐。這個主題對象在狀態(tài)發(fā)生改變時懊亡,會通知所有觀察者對象,使它們能夠自動更新自己乎串。觀察者模式中存在兩類角色:- Subject 類:抽象主題類
它把所有對觀察者對象的引用保存在一個集合里店枣,沒個主題都能有任意數(shù)量的觀察者。抽象主題提供接口灌闺,可以增加或刪除觀察者public interface Subject<O extends Observer> { void add(O o); void delete(O o); void notify(); } public abstract class AbstractSubject implements Subject { public List<Observer> observers; public String state; public AbstractSubject() { this.observers = new ArrayList<>(); } } // 抽象主題的具體實現(xiàn)艰争,其中包含主題的狀態(tài),當狀態(tài)發(fā)生改變時通知該主題所有的觀察者 public class Concrete1Subject extends AbstractSubject { @Override public void add(Observer o) { observers.add(o); } @Override public void delete(Observer o) { observers.remove(o); } @Override public void notifyObserver() { for(Observer o : observers) { o.update(state); } } public void changeState(String state) { this.state = state; notifyObserver(); } }
- 觀察者 Observer 類:抽象觀察者
為所有具體的觀察者提供接口桂对,在得到主題的通知時執(zhí)行更新操作。public interface Observer { void update(Object msg); } public class ConcreteObserver implements Observer { private String name; private Object oState; public ConcreteObserver(String name) { super(); this.name = name; } @Override public void update(Object msg) { oState = msg; System.out.println(name + " update state to " + msg); } } public static void main(String[] args) { Concrete1Subject subject = new Concrete1Subject(); ConcreteObserver observer1 = new ConcreteObserver("observer1"); ConcreteObserver observer2 = new ConcreteObserver("observer2"); subject.add(observer1); subject.add(observer2); subject.changeState("state1"); }
- Subject 類:抽象主題類
-
Java 中的事件機制
Java SE 中提供了事件的基礎(chǔ)接口:EventObject 類和 EventListener 類鸠匀。-
事件對象:EventObject蕉斜,事件對象中封裝了事件源(source)
public class EventObject implements java.io.Serializable { private static final long serialVersionUID = 5516075349620653480L; protected transient Object source; public EventObject(Object source) { if (source == null) throw new IllegalArgumentException("null source"); this.source = source; } public Object getSource() { return source; } public String toString() { return getClass().getName() + "[source=" + source + "]"; } }
-
事件監(jiān)聽:EventListener
定義了一個事件監(jiān)聽器的接口,所有監(jiān)聽器的具體實現(xiàn)需要實現(xiàn)該接口。public interface EventListener { }
事件源:EventObject 中封裝的事件源 source是具有行為的任何 Java 對象宅此,其具有的行為是為了觸發(fā)事件机错。
三者的關(guān)系為,在事件源中注冊監(jiān)聽器父腕,當事件源發(fā)生某個具體的事件時弱匪,會調(diào)用監(jiān)聽器的方法,并將事件對象傳遞給監(jiān)聽器璧亮,同時監(jiān)聽器可以利用時間對象操作事件源萧诫。
具體實現(xiàn)代碼:// 1. 事件對象 public class TestEvent extends EventObject { public TestEvent(Object source) { super(source); } } public class TestListener implements EventListener { public void notifyListener(EventObject eventObject) { if(eventObject instanceof TestEvent) { EventSource source = (EventSource) eventObject.getSource(); String sourceState = source.getSourceState(); System.out.println("source state changed to " + sourceState); } } } public class EventSource { private String sourceState = "0"; private List<EventListener> listeners; public EventSource() { listeners = new ArrayList<>(); } public EventSource(List<EventListener> listeners) { this.listeners = listeners; } public void addListener(EventListener eventListener) { listeners.add(eventListener); } public String getSourceState() { return sourceState; } public void setSourceState(String sourceState) { this.sourceState = sourceState; } public void changeState(String state) { sourceState = state; for(EventListener eventListener : listeners) { if(eventListener instanceof TestListener) { ((TestListener) eventListener).notifyListener(new TestEvent(this)); } } } public static void main(String[] args) { EventSource eventSource = new EventSource(); TestListener testListener = new TestListener(); eventSource.addListener(testListener); eventSource.changeState("1"); } }
-
-
Spring 中的事件機制
-
Spring 事件機制基礎(chǔ)
Spring 中事件機制的支持主要包含2個頂級的接口,其作用于Java事件的兩個類基本相同:ApplicationEvent, ApplicationListener枝嘶。- ApplicationEvent : Spring 中對事件的抽象
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; } }
- ApplicationListener: Spring 事件的監(jiān)聽器
@FunctionalInterface public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }
- ApplicationEventPublisher:事件發(fā)布器
查看 ApplicationContext 的繼承關(guān)系可知帘饶,其繼承了 ApplicationEventPublisher 接口,因此 Spring Ioc 容器本身可以發(fā)布事件群扶。
@FunctionalInterface public interface ApplicationEventPublisher { /** * Notify all <strong>matching</strong> listeners registered with this * application of an application event. Events may be framework events * (such as RequestHandledEvent) or application-specific events. * @param event the event to publish * @see org.springframework.web.context.support.RequestHandledEvent */ default void publishEvent(ApplicationEvent event) { publishEvent((Object) event); } /** * Notify all <strong>matching</strong> listeners registered with this * application of an event. * <p>If the specified {@code event} is not an {@link ApplicationEvent}, * it is wrapped in a {@link PayloadApplicationEvent}. * @param event the event to publish * @since 4.2 * @see PayloadApplicationEvent */ void publishEvent(Object event); }
-
代碼實現(xiàn)
- 自定義 ApplicationEvent
public class MySpringEvent extends ApplicationEvent { private String name; public MySpringEvent(Object source, String name) { super(source); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
- 自定義監(jiān)聽器并注入至 Ioc 容器
@Component public class MySpringListener implements ApplicationListener<MySpringEvent> { @Override public void onApplicationEvent(MySpringEvent event) { Object source = event.getSource(); String name = event.getName(); System.out.println("監(jiān)聽到事件 MySpringEvent及刻,name = " + name); } }
- 測試方法
@Configuration @ComponentScan("com.note.spring.listener.spring") public class MyConfig { } public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); applicationContext.publishEvent(new MySpringEvent("event-name1", "event")); }
-
-
總結(jié)
全文主要介紹了觀察者模式、Java 事件機制竞阐、Spring 事件機制三部分的內(nèi)容缴饭,并分別給出了代碼實現(xiàn)。- 觀察者模式中骆莹,主要涉及了 Subject 和 Observer 兩個角色颗搂, subject 中包含了對應(yīng)觀察者的列表,并在 subject 狀態(tài)發(fā)生變化是通知所有的觀察者汪疮。
- Java 事件機制中涉及到了兩個基礎(chǔ)類:EventObject 和 EventListener峭火,其中 EventObject 中包含了事件源,由事件源觸發(fā) listener
- Spring 事件機制中包含了三個基礎(chǔ)類: ApplicationEvent智嚷、ApplicationListener卖丸、ApplicationEventPublisher,使用時結(jié)合了 ApplicationContext 容器盏道,后續(xù)的文章中會通過源碼分析詳細介紹原理稍浆。