Spring事件发布/监听机制

本文详细介绍了Spring中的事件处理机制,包括观察者模式、ApplicationEvent和ApplicationListener接口、事件管理者ApplicationEventMulticaster、事件发布者ApplicationEventPublisher以及注解驱动的事件监听@EventListener。Spring事件监听器通过实现ApplicationListener接口,当事件发布时,会接收到事件通知。通过SmartApplicationListener和GenericApplicationListener可以实现更灵活的事件过滤和监听。Spring的事件发布是通过ApplicationContext实现,可以通过@EventListener注解实现异步或同步的事件处理。
摘要由CSDN通过智能技术生成

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
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值