美文网首页
Spring 事件机制概述

Spring 事件机制概述

作者: 逗逗罗 | 来源:发表于2020-12-09 15:52 被阅读0次

    Spring 事件机制是观察者模式的典型应用,本文将由浅入深从观察者模式、java事件机制、Spring事件机制三个部分来进行分析。

    • 观察者模式
      观察者模式是软件设计中常用的设计模式之一。定义对象间的一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使它们能够自动更新自己。观察者模式中存在两类角色:

      1. 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();
            }
        }
        
      2. 观察者 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");
        }
        
    • Java 中的事件机制
      Java SE 中提供了事件的基础接口:EventObject 类和 EventListener 类。

      1. 事件对象: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 + "]";
            }
        }
        
      2. 事件监听:EventListener
        定义了一个事件监听器的接口,所有监听器的具体实现需要实现该接口。

        public interface EventListener {
        }
        
      3. 事件源: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。

        1. 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;
            }
        }
        
        1. 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);
        
        }
        
        1. 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);
        
        }
        
      • 代码实现

        1. 自定义 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;
            }
        }
        
        1. 自定义监听器并注入至 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);
            }
        }
        
        1. 测试方法
        @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 事件机制三部分的内容,并分别给出了代码实现。

      1. 观察者模式中,主要涉及了 Subject 和 Observer 两个角色, subject 中包含了对应观察者的列表,并在 subject 状态发生变化是通知所有的观察者。
      2. Java 事件机制中涉及到了两个基础类:EventObject 和 EventListener,其中 EventObject 中包含了事件源,由事件源触发 listener
      3. Spring 事件机制中包含了三个基础类: ApplicationEvent、ApplicationListener、ApplicationEventPublisher,使用时结合了 ApplicationContext 容器,后续的文章中会通过源码分析详细介绍原理。

    相关文章

      网友评论

          本文标题:Spring 事件机制概述

          本文链接:https://www.haomeiwen.com/subject/yyvhgktx.html