Spring的容器内部事件发布

文/杜琪(简书作者)

原文链接: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容器内的事件发布机制。

时间: 2024-10-23 13:13:26

Spring的容器内部事件发布的相关文章

【spring源码学习】spring的事件发布监听机制源码解析

[一]相关源代码类 (1)spring的事件发布监听机制的核心管理类:org.springframework.context.event.SimpleApplicationEventMulticaster. =>该类的初始化是放在项目加载时,在ioc容器xml配置文件解析加载完毕后,注册bean创建前后置处理实现类(BeanPostProcessor 接口实现),beanFactory配置处理(BeanFactoryPostProcessor接口实现)后,初始化该事件发布监听机制的核心类. pu

Spring中ApplicationContext的事件机制

   ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理.如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发.     Spring的事件框架有如下两个重要的成员: ApplicationE

2.Spring常用配置—5.事件

1.点睛Spring的事件(Application Event)为Bean与Bean之间的消息通信提供了支持.当一个Bean处理完一个任务之后,希望另一个Bean知道并能做相应的处理,这时我们就需要让另外一个Bean监听当前Bean所发送的事件.Spring的事件需要遵循如下流程:(1)自定义事件,继承ApplicationEvent(2)定义事件监听器,实现ApplicationListener(3)使用容器发布事件2.示例(1)自定义事件(2)事件监听器实现ApplicationListen

Spring中ApplicationContext的事件机制(二 内定事件)

在Spring中已经定义了五个标准事件,分别介绍如下: 1)ContextRefreshedEvent:当ApplicationContext初始化或者刷新时触发该事件. 2)ContextClosedEvent:当ApplicationContext被关闭时触发该事件.容器被关闭时,其管理的所有 单例Bean都被销毁. 3)RequestHandleEvent:在Web应用中,当一个http请求(request)结束触发该事件. ContestStartedEvent:Spring2.5新增的

《Spring攻略(第2版)》——1.2 配置Spring IoC容器中的Bean

1.2 配置Spring IoC容器中的Bean 1.2.1 问题 Spring提供了一个强大的IoC容器来管理组成应用的bean.为了利用容器服务,你必须配置运行于Spring IoC容器中的Bean. 1.2.2 解决方案 你可以通过XML文件.属性文件.注释甚至API来配置Spring IoC容器中的Bean. Spring允许你在一个或者多个bean配置文件中配置bean.对于简单的应用程序,可以在单个配置文件中集中配置bean.但是对于有许多bean的大型应用,你应该根据其功能(例如控

spring IOC容器实现探讨

   spring IOC容器的实现,一开始我被复杂的接口和类所掩埋,看不清整体的思路和设计,踟蹰于代码丛林中,摸不清前进的方向.一开始我就决定只研读以xml文件做配置文件的XmlFactoryBean的具体实现为主要目标,渐渐地有了点感觉,用UML把spring中的bean工厂体系展现出来之后就更清晰了,让你不得不感叹设计的精巧和复杂.本文只是我个人对spring IOC实现的理解,如有错误,请不吝赐教,谢谢.     首先,需要理解的是spring容器中bean的生命周期,<spring i

spring-关于Spring父子容器的事务处理问题

问题描述 关于Spring父子容器的事务处理问题 10C 今天在看项目的配置,在SpringMVC(子容器)中不注解service,在父容器中不注解controller,网上搜了一下,引用原话是:_子容器对Controller进行扫描装配时装配了@Service注解的实例 (@Controller 实例依赖@Service实例),而该实例理应由父容器进行初始化以保证事务的增强处理_ 我的问题是:保证事务的增强处理是什么意思? 子容器是可以访问父容器的内容的吧,那么父容器做到的子容器也可以做到的应

《Spring攻略(第2版)》——第1章 Spring简介 1.1实例化Spring IoC容器

第1章 Spring简介 在本章中,你将参加关于Spring.核心容器以及容器所提供的一些全局可用设施的一个速成班(或者一次复习),你还将了解Spring XML配置格式,以及注释驱动的支持.本章将带给你应付本书余下部分中引入的概念所需要的知识.你将学习Spring IoC容器中的基本组件配置.在Spring框架的核心部分,IoC容器的设计具有高度的适应性和可配置性,提供了使你的组件配置尽可能简单的一组工具.你能够很简单地设置运行于Spring IoC容器中的组件. 在Spring中,组件也被称

Spring Integration 4.3.10 发布,Spring 消息通信

Spring Integration 4.3.10 发布了.Spring Integration 能在基于 Spring 的应用中进行简单的消息通信,并通过简单的适配器与外部系统集成.这些适配器提供了一个更高级别的抽象,超越了 Spring 对远程调用.消息和调度的支持.其主要目标是在保持关注点分离的同时,为构建企业集成解决方案提供一个简单的模型,该模型对产出可维护.可测试的代码来说是必不可少的. 更新内容: Bug [INT-4248] - RedisLockRegistry does not