Spring的容器内部事件发布

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介:
文/杜琪(简书作者)
原文链接:http://www.jianshu.com/p/4f0ad3bb98f0
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

自定义事件机制

给出自定义事件类型在某些应用场景下,我们希望关注特定功能的执行情况,这种功能的开始或者结束或者异常都可以看做一个事件,因此需要定义自己的事件类型。

package com.javadu.event;

import java.util.EventObject;

public class MethodExecutionEvent extends EventObject {
    private String methodName;

    public MethodExecutionEvent(Object source) {
        super(source);
    }

    public MethodExecutionEvent(Object source, String methodName) {
        super(source);
        this.methodName = methodName;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
}

实现针对自定义事件类的事件监听器接口监听器负责处理具体的事件,当某个事件发生时,监听器也给出具体的回应。在这个例子中,监听器会在目标方法执行开始或者执行结束时响应对应的事件并处理。

package com.javadu.event;

import java.util.EventListener;

public interface MethodExecutionEventListener extends EventListener {
    void onMethodBegin(MethodExecutionEvent evt);
    void onMethodEnd(MethodExecutionEvent evt);
}
EventListener接口的作用仅仅在于“标记”,具体要提供哪些功能需要开发者自己定义,而且,还需要为自己定义的接口提供一个默认的实现类——只有接口的话什么也做不了。
package com.javadu.event;

public class SimpleMethodExecutionEventListener implements MethodExecutionEventListener {
    public void onMethodBegin(MethodExecutionEvent evt) {
        String methodName = evt.getMethodName();
        System.out.println("start to execute the method[" + methodName + "]");
    }

    public void onMethodEnd(MethodExecutionEvent evt) {
        String methodName = evt.getMethodName();
        System.out.println("finished to execute the method[" + methodName + "]");
    }
}


组合事件类和监听器,发布事件这个是一个测试用例,首先需要准备测试环境:事件类+监听器;然后再发布事件,就可以看到监听器对事件的处理。
public class MethodExecutionEventPublisher {
  private List<MethodExecutionEventListener> listeners = new ArrayList<MethodExecutionEventListener>();

  public void addMethodExecutionEventListener(MethodExecutionEventListener listener) {
      this.listeners.add(listener);
  }

  public void methodToMonitor() {
      MethodExecutionEvent event2Publish = new MethodExecutionEvent(this, "methodToMonitor");
      //发布方法开始执行的事件
      publishEvent(MethodExecutionStatus.BEGIN, event2Publish);

      //执行实际的方法逻辑
      //……
      //发布方法执行结束的事件
      publishEvent(MethodExecutionStatus.END, event2Publish);
  }

  protected void publishEvent(MethodExecutionStatus status, MethodExecutionEvent methodExecutionEvent) {
      List<MethodExecutionEventListener> copyListeners = new ArrayList<MethodExecutionEventListener>(listeners);
      for (MethodExecutionEventListener listener: copyListeners) { //发布事件,同时调用对应的监听器方法
          if (MethodExecutionStatus.BEGIN.equals(status)) {
              listener.onMethodBegin(methodExecutionEvent);
          } else {
              listener.onMethodEnd(methodExecutionEvent);
          }
      }
  }

  public void removeListener(MethodExecutionEventListener listener) {
      if (this.listeners.contains(listener)) {
          this.listeners.remove(listener);
      }
  }

  public void removeAllListeners() {
      this.listeners.clear();
  }

  public static void main(String[] args) {
      MethodExecutionEventPublisher eventPublisher = new MethodExecutionEventPublisher();
      eventPublisher.addMethodExecutionEventListener(new SimpleMethodExecutionEventListener()); //组合事件类和监听器
      eventPublisher.methodToMonitor();//发布事件
  }
}
Java SE中标准的自定义事件实现就是这个样子,涉及三个角色,即自定义事件类型、自定义的事件监听器和自定义的事件发布者,如下图所示:



JavaSE中自定义的事件结构图

Spring 的容器内事件发布类结构
Spring的ApplicationContext容器内部允许以 org.springframework.context.ApplicationEvent的形式发布事件, 容器内注册的org.springframework.context.ApplicationListener类型的bean定义会被ApplicationContext容器自动识别,它们负责监容器内发布的所有ApplicationEvent类型的事件。也就是说,一旦容器内发布ApplicationEvent及其子类型的事件,注册到容器的ApplicationListener就会对这些事件进行处理。


ApplicationEvent:Spring容器内的事件类型,继承自java.util.EventObject,这是一个抽象类,Spring提供了三个具体的实现——ContextCloseEvent、ContextRefreshedEvent和RequestHandleEvent。

ApplicationListener: Spring容器内使用的事件监听接口,继承自java.util.EventListener。ApplicationContext容器启动时,会自动识别并加载EventListener类型的bean定义,一旦容器中有ApplicationEvent事件发布,就会通知这些监听器。

ApplicationContext: ApplicationContext容器的具体实现类在实现事件的发布和事件监 器的注册方面,并没事必躬亲,而是把这些活儿转包给了一个称作org.springframework.context.event.ApplicationEventMulticaster的接口。该接口定义了具体事件监器的注册管理以及事件发布的方法,但接口终归是接口,还得有具体实现。ApplicationEventMulticaster有一抽象实现类:org.spring-framework.context.event.AbstractApplicationEventMulticaster,它实现了事件监 器的管理功能。出于灵活性和扩展性考虑,事件的发布功能则委托给了其子类。org.springframework.context.event.SimpleApplicationEventMulticaster 是 Spring提供的AbstractApplicationEventMulticaster的一个子类实现,添加了事件发布功能的实现。

综上,Spring容器内部事件发布的类图描述如下:

Spring容器内部事件发布实现类图

应用场景
Spring的ApplicationContext容器内的事件发布机制,主要用于单一容器内的简单消息通知和处理,并不适合分布式、多进程、多容器之间的事件通知。虽然可以通过Spring的Remoting支持,“曲折一点”来实现较为复杂的需求,但是难免弊大于利,失大于得。其他消息机制处理较复杂场景或许更合适。所以,我们应该在合适的地点、合适的需求分析的前提下,合理地使用Spring提供的ApplicationContext容器内的事件发布机制。
目录
相关文章
|
13天前
|
存储 安全 Java
事件的力量:探索Spring框架中的事件处理机制
事件的力量:探索Spring框架中的事件处理机制
27 0
|
2月前
|
XML Java 数据格式
编织Spring魔法:解读核心容器中的Beans机制【beans 一】
编织Spring魔法:解读核心容器中的Beans机制【beans 一】
42 0
|
2月前
|
XML Java 数据格式
Spring IoC容器初始化过程(xml形式)
Spring IoC容器初始化过程(xml形式)
46 0
|
1月前
|
Java Spring
除了spring自带的事件,你还可以这样使用事件
除了spring自带的事件,你还可以这样使用事件
14 3
|
1月前
|
Java 容器 Spring
【spring(一)】核心容器总结
【spring(一)】核心容器总结
|
1月前
|
Java 开发者 容器
【Java】深入了解Spring容器的两个关键组件
【Java】深入了解Spring容器的两个关键组件
10 0
|
1月前
|
存储 安全 Java
全面探索Spring框架中的事件处理机制
在现代应用程序中,各个组件之间的通信是至关重要的。想象一下,你的应用程序中的各个模块像是一个巨大的交响乐团,每个模块都是一位音乐家,而Spring事件机制就像是指挥家,将所有音乐家协调得天衣无缝。这种松耦合的通信方式使你的应用程序更加灵活、可维护,而且能够轻松应对变化。现在,让我们进入这个令人兴奋的音乐厅,探索Spring事件的世界。
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (下)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
|
2月前
|
前端开发 Java 数据格式
10个知识点让你读懂spring MVC容器
随着 Spring Boot 逐步全面覆盖到我们的项目之中,我们已经基本忘却当年经典的 Servlet + Spring MVC 的组合,那让人熟悉的 web.xml 配置。而本文,我们想先抛开 Spring Boot 到一旁,回到从前,一起来看看 Servlet 是怎么和 Spring MVC 集成,怎么来初始化 Spring 容器的。
20 1