ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring 事件驱动,自定义事件监听

2021-09-20 11:04:56  阅读:330  来源: 互联网

标签:自定义 Spring ApplicationEvent event 事件驱动 source 事件 监听器 public


目录


 

概述

spring引入了事件机制,支持 ApplicationEvent(应用事件),可以对指定事件进行监听处理。
 

事件驱动的3要素

  • 事件:具有事件源、发生时间2个属性
  • 事件发布器:负责发布事件
  • 事件监听器:监听指定类型的事件,
     

spring的事件驱动模型

观察者模式的典型应用,监听器订阅指定类型的事件,事件发布器发布事件时,会自动通知订阅了该事件类型的所有监听器。

 

源码分析

ApplicationEvent 应用事件

public abstract class ApplicationEvent extends EventObject {

	private static final long serialVersionUID = 7099057708183571937L;

	//事件的发生时间,long型时间戳
	private final long timestamp;

	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}

	public ApplicationEvent(Object source, Clock clock) {
		super(source);
		this.timestamp = clock.millis();
	}

	public final long getTimestamp() {
		return this.timestamp;
	}

}

jdk自带的对象事件 EventObject 定义了一个Object类型的成员变量表示事件源,ApplicationEvent 在 EventObject 的基础上增加了一个long型的成员变量表示事件的发生时间。

 

spring中常见的事件类型

ApplicationEvent 表示spring的应用事件,是spring事件的公共父类,这个类有很多子类,表示具体的事件类型。
 

spring常见的事件类型(5种标准事件)

方法名称触发时机对应的触发方法
ContextRefreshedEvent
上下文更新事件
Event raised when an ApplicationContext gets initialized or refreshed
容器被初始化或被更新时触发
调用 ConfigurableApplicationContex t的 refresh() 方法
ContextStartedEvent
上下文开始事件
Event raised when an ApplicationContext gets started
容器启动时触发
调用 ConfigurableApplicationContext 的 start() 方法
ContextStoppedEvent
上下文停止事件
Event raised when an ApplicationContext gets stopped
容器被停止时触发
调用 ConfigurableApplicationContext 的 stop() 方法
ContextClosedEvent
上下文关闭事件
Event raised when an ApplicationContext gets closed
容器被关闭时触发
调用 ConfigurableApplicationContext 的 close() 方法
RequestHandledEvent
请求(已)处理事件
Event raised when a request is handled within an ApplicationContext
请求被处理时触发
说明:如果是 springmvc,会直接使用 RequestHandledEvent 的子类 ServletRequestHandledEvent

start()、stop() 都是 ConfigurableApplicationContext 接口从 Lifecycle 接口继承的,以上4个方法 ConfigurableApplicationContext 都未提供实现。

spring支持自定义的应用事件,可以继承 ApplicationEvent 实现自定义的应用事件。

 

ApplicationListener 事件监听器

//继承了jdk自带的事件监听器 EventListener,泛型指定要监听的事件类型
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	//处理事件
	void onApplicationEvent(E event);

	static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {
		return event -> consumer.accept(event.getPayload());
	}

}

 

ApplicationEventPublisher 事件发布器

@FunctionalInterface
public interface ApplicationEventPublisher {

	//发布事件,默认实现是调用下面的方法
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}

	//发布事件,参数是要发布的事件
	void publishEvent(Object event);

}
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
	//...
}

事件发布器只被 ApplicationContext 系列接口继承实现了,可以调用ApplicationContext 实例发布事件。

 

实际使用

自定义事件

/**
 * 自定义事件,需要继承 ApplicationEvent
 */
public class MyApplicationEvent extends ApplicationEvent {

    /**
     * 在构造方法中调用父类对应的构造方法
     *
     * @param source 事件源
     */
    public MyApplicationEvent(Object source) {
        super(source);
    }

}

 

编写事件监听器

事件监听器有2种写法
 
1、ApplicationListener 接口方式

/**
 * 自定义的事件监听器,需要实现 ApplicationListener
 * 泛型指定要监听的事件类型,ApplicationEvent 则表示监听所有的spring应用事件
 */
@Component  //放到容器中
public class MyApplicationEventListener implements ApplicationListener<MyApplicationEvent> {

    /**
     * 处理事件。可通过event获取事件源、发生时间
     * 如果处理很耗时,可以使用标注 @Async 异步执行
     *
     * @param event
     */
    @Override
    public void onApplicationEvent(MyApplicationEvent event) {
        System.out.println("接收到事件:" + event);
    }

}

一个类对应一个监听器,往往需要编写多个自定义的监听器类
 

2、注解方式

@Component  //放到容器中
public class MyApplicationEventListener {

    /**
     * 使用 @EventListener 标识为监听器,形参类型即要监听的事件类型
     * 如果处理很耗时,可以使用标注 @Async 异步执行
     *
     * @param event 事件
     */
    @EventListener
    public void MyApplicationEvent(MyApplicationEvent event) {
        System.out.println("接收到事件:" + event);
    }

}

一个方法对应一个监听器,可在一个类中写多个监听器
 

说明

如果监听器中处理事件的方法执行很耗时,可以使用springboot自带的异步方法@Async,让方法异步执行,不阻塞主线程。

异步方法需要在引导类上加 @EnableAsync 才会生效

 

发布事件

/**
 * 应用上下文
 */
@Autowired
private ApplicationContext applicationContext;

/**
 * 发布事件
 *
 * @param source 事件源
 */
public void publishEvent(Object source) {
    //创建事件
    MyApplicationEvent myApplicationEvent = new MyApplicationEvent(source);
    //发布事件。会自动通知订阅了此事件类型的所有监听器
    applicationContext.publishEvent(myApplicationEvent);
}

标签:自定义,Spring,ApplicationEvent,event,事件驱动,source,事件,监听器,public
来源: https://blog.csdn.net/chy_18883701161/article/details/120387394

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有