Spring 框架——事件驱动模型

目录

1.概述

(1)Spring 事件驱动模型 是 Spring 框架中的一种编程模型,也被称为发布/订阅模型 ,通过使用观察者模式事件机制 ,实现了组件之间基于事件的解耦和通信。在 Spring 中,事件驱动模型建立在应用上下文事件 (ApplicationContextEvent) 的基础上。应用上下文事件是一种用于描述应用状态改变的事件,如应用上下文初始化完成、上下文刷新、上下文关闭等。

(2)通过事件驱动模型,Spring 框架提供了更灵活、松散耦合的方式来实现组件之间的通信和解耦。开发者可以定义自己的事件,并通过事件监听器来处理,实现自定义的业务逻辑,扩展框架的行为,并能够更容易地实现可测试、可维护和可扩展的应用程序。

有关观察者模式的相关知识可以参考Java 设计模式------观察者模式

2.三种角色

2.1.事件角色

(1)事件是系统中发生的特定动作或者状态的表示。它可以是一个普通的 Java 对象,通常包含与该事件相关的数据和信息。例如,一个用户注册事件可以包含用户的姓名、邮箱等信息。

(2)在 Spring 中,org.springframework.context 包下的抽象类 ApplicationEvent 充当了事件的角色,它继承了 java.util.EventObject 类。并且Spring 中默认存在以下 4 种事件,它们都是继承了 ApplicationContextEvent 类(该类继承自 ApplicationEvent):

  • ContextClosedEvent:表示应用程序上下文关闭事件,触发时机是在应用程序上下文关闭时;
  • ContextRefreshedEvent:表示应用程序上下文刷新事件,触发时机是在应用程序上下文初始化及刷新完成后
  • ContextStartedEvent:表示应用程序上下文启动事件,触发时机是在应用程序上下文启动时;
  • ContextStoppedEvent:表示应用程序上下文停止事件,触发时机是在应用程序上下文停止时;

(3)上述类之间的关系如下图所示:

2.2.事件监听者角色

接口 ApplicationListener 充当了事件监听者角色,其源码如下所示。该接口中定义了一个名为 onApplicationEvent() 的方法来处理事件 ApplicationEvent。因此,在 Spring 中我们只需该接口的 onApplicationEvent() 方法即可完成监听事件。

java 复制代码
package org.springframework.context;

import java.util.EventListener;

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);
}

2.3.事件发布者角色

接口 ApplicationEventPublisher 充当了事件发布者角色,其源码如下所示。该接口中的 publishEvent() 方法的具体实现是在AbstractApplicationContext 类中,具体细节此处就不再过多描述,感兴趣的读者可以去阅读其源码。

java 复制代码
package org.springframework.context;

@FunctionalInterface
public interface ApplicationEventPublisher {
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}

	void publishEvent(Object event);
}

(2)在事件驱动模型中,发布者 (Publisher) 和订阅者 (Subscriber) 是模型的关键角色。发布者通过发布事件的方式进行通知,而订阅者通过订阅(订阅)事件的方式接收通知。发布者和订阅者之间的关系是松散耦合的,发布者不需要知道订阅者的具体细节,只需要发布事件,并由框架负责将事件传递给订阅者。

(3)在 Spring 框架中,应用上下文充当事件的发布者,而事件监听器 (Event Listener) 充当事件的订阅者。监听器可以通过实现 ApplicationListener 接口或使用 @EventListener 注解来订阅应用上下文事件。当事件被发布时,相应的监听器会接收到事件并执行相应的逻辑,实现事件驱动的编程。

3.示例

(1)使用 Spring 的事件驱动模型的一般步骤如下:

  • 定义事件:继承抽象类 ApplicationEvent,并且写相应的构造函数;
  • 定义事件监听者:实现 ApplicationListener 接口,重写 onApplicationEvent() 方法;
  • 定义事件发送者:发送者调用 ApplicationContext 中的 publishEvent 方法来发送事件消息;

(2)示例代码如下所示:

  • 首先,定义一个继承自 ApplicationEvent 的事件类 CustomEvent
java 复制代码
import org.springframework.context.ApplicationEvent;

public class CustomEvent extends ApplicationEvent {

   private String message;

   public CustomEvent(Object source, String message) {
      super(source);
      this.message = message;
   }

   public String getMessage() {
      return message;
   }
}
  • 接下来,创建一个实现了 ApplicationListener 的事件监听器 CustomEventListener
java 复制代码
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
	@Override
	public void onApplicationEvent(CustomEvent customEvent) {
		String message = customEvent.getMessage();
		System.out.println("接收到的信息为: " + message);
	}
}
  • 然后,创建一个事件发布者 EventPublisher
java 复制代码
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

@Component
public class CustomPublisher {
	@Autowired
	private ApplicationContext applicationContext;
	
	public void publish(CustomEvent customEvent) {
		this.applicationContext.publishEvent(customEvent);
	}
}
  • 当调用 CustomPublisherpublish() 方法时,比如 customPublisher.publish("Hello, World!") ,控制台就会打印出:
java 复制代码
接收到的信息为: Hello, World!
相关推荐
曾令胜3 小时前
excel导出使用arthas动态追踪方法调用耗时后性能优化的过程
spring·性能优化·excel
多云几多3 小时前
Yudao单体项目 springboot Admin安全验证开启
java·spring boot·spring·springbootadmin
摇滚侠5 小时前
Spring Boot 3零基础教程,Spring Intializer,笔记05
spring boot·笔记·spring
兮动人6 小时前
Spring Bean耗时分析工具
java·后端·spring·bean耗时分析工具
MESSIR226 小时前
Spring IOC(控制反转)中常用注解
java·spring
hello 早上好10 小时前
深入 Spring 条件化配置底层:从硬编码到通用注解的实现原理
java·后端·spring
亚林瓜子10 小时前
Spring中Date日期序列化与反序列化中格式设置
java·后端·spring·jackson·date
哞哞不熬夜15 小时前
JavaEE--Spring MVC
spring·java-ee·mvc
Java水解15 小时前
深入剖析Spring Boot依赖注入顺序:从原理到实战
后端·spring
椎49516 小时前
web后端开发——原理
spring boot·spring·mybatis