Spring 事件机制是观察者模式的典型应用,本文将由浅入深从观察者模式、java事件机制、Spring事件机制三个部分来进行分析。
-
观察者模式
观察者模式是软件设计中常用的设计模式之一。定义对象间的一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使它们能够自动更新自己。观察者模式中存在两类角色:- Subject 类:抽象主题类
它把所有对观察者对象的引用保存在一个集合里,没个主题都能有任意数量的观察者。抽象主题提供接口,可以增加或删除观察者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<>(); } } // 抽象主题的具体实现,其中包含主题的状态,当状态发生改变时通知该主题所有的观察者 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 类:抽象观察者
为所有具体的观察者提供接口,在得到主题的通知时执行更新操作。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 中提供了事件的基础接口: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 + "]"; } }
-
事件监听:EventListener
定义了一个事件监听器的接口,所有监听器的具体实现需要实现该接口。public interface EventListener { }
事件源:EventObject 中封装的事件源 source是具有行为的任何 Java 对象,其具有的行为是为了触发事件。
三者的关系为,在事件源中注册监听器,当事件源发生某个具体的事件时,会调用监听器的方法,并将事件对象传递给监听器,同时监听器可以利用时间对象操作事件源。
具体实现代码:// 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 事件机制基础
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 事件的监听器
@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:事件发布器
查看 ApplicationContext 的继承关系可知,其继承了 ApplicationEventPublisher 接口,因此 Spring Ioc 容器本身可以发布事件。
@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); }
-
代码实现
- 自定义 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; } }
- 自定义监听器并注入至 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("监听到事件 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")); }
-
-
总结
全文主要介绍了观察者模式、Java 事件机制、Spring 事件机制三部分的内容,并分别给出了代码实现。- 观察者模式中,主要涉及了 Subject 和 Observer 两个角色, subject 中包含了对应观察者的列表,并在 subject 状态发生变化是通知所有的观察者。
- Java 事件机制中涉及到了两个基础类:EventObject 和 EventListener,其中 EventObject 中包含了事件源,由事件源触发 listener
- Spring 事件机制中包含了三个基础类: ApplicationEvent、ApplicationListener、ApplicationEventPublisher,使用时结合了 ApplicationContext 容器,后续的文章中会通过源码分析详细介绍原理。