Spring特性——事件驱动模型

原创内容,转载请注明出处

1、Spring事件模型

事件驱动模型是一种观察者模式的典型应用,或者叫发布——订阅模型,Java中awt的事件机制和Spring的事件机制都是观察者模式的应用。

一般都是发布者有更改变动时,订阅者会接收到发布者的变动通知。

举个通用的例子网上看新闻,首先我们需要去订阅新闻,当有新的新闻时,网站会自动推送新闻给已经订阅过该新闻的用户。

新建新闻Xinwen,代码如下

 

package com.test.springevent;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;

public class Xinwen implements ApplicationContextAware{

	private ApplicationContext applicationContext;
	private String content;
	
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

	public ApplicationContext getApplicationContext() {
		return applicationContext;
	}
	
	public void process(){
		content = "新闻:小米销售额在国内第一";
		applicationContext.publishEvent(new XinwenApplicationEvent(content));
	}
	

	
	
}

 

新建新闻事件XinwenApplicationEvent,代码如下

 

package com.test.springevent;

import org.springframework.context.ApplicationEvent;

public class XinwenApplicationEvent extends ApplicationEvent {

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

}

 

创建用户1 User1,代码如下

package com.test.springevent;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class User1 implements ApplicationListener<ApplicationEvent> {

	public void onApplicationEvent(ApplicationEvent event) {
		if(event instanceof XinwenApplicationEvent){
			System.out.println("用户1查看新闻");
			System.out.println(event.getSource());
		}
	}

}

 

创建用户2 User2,代码如下

package com.test.springevent;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

public class User2 implements ApplicationListener<ApplicationEvent> {

	public void onApplicationEvent(ApplicationEvent event) {
		if(event instanceof XinwenApplicationEvent){
			System.out.println("用户2查看新闻");
			System.out.println(event.getSource());
		}
	}

}

 

创建bean.xml文件,内容如下

 

    <!-- 测试Spring事件机制 -->
    <bean class="com.test.springevent.User1"/>
    <bean class="com.test.springevent.User2"/>
    <bean id="xinwen" class="com.test.springevent.Xinwen"/>

 

创建Junit测试代码

	/**
	 * 测试spring事件
	 */
	@Test
	public void testSpringEvent(){
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml"); 
		Xinwen xinwen = (Xinwen) applicationContext.getBean("xinwen");
		xinwen.process();
	}

 

创建bean.xml

 

测试结果如下

 

 

2、代码分析

1.在Spring的ApplicationContext篇幅中有大致提到Spring事件多路广播器ApplicationEventMulticaster的初始化和监听器ApplicationListener的注册。

 

2.Spring的监听器ApplicationListener实现了Java的EventListener事件监听器接口类,故而我们只需实现ApplicationListener接口。

 

3.Spring事件ApplicationEvent类继承了EventObject接口类,如有需要,我们只需要继承ApplicationEvent事件。

 

4.Spring发布事件接口类是ApplicationEventPublisher,然而ApplicationContext实现了ApplicationEventPublisher接口,故而可以直接调用ApplicationContext的PublishEvent方法发布事件。

 

5.跟踪ApplicationContext的发布事件方法代码可知,实际ApplicationContext容器是委托事件多路广播器ApplicationEventMulticaster来发布事件的。ApplicationEventMulticaster在IOC容器初始化时被初始化,同时会将ApplicationLisener监听器注册给事件多路广播器,当然IOC容器也支持代码式注册监听器。

 

6.ApplicationEventMulticaster(实现子类SimpleApplicationEventMulticaster)在发布事件时,支持异步发布,只需在ApplicationEventMulticaster实例中注入Java的Executor实例,即通过多线程来完成事件异步发布。

3、Spring事件异步发布

 在bean.xml文件添加如下bean配置。

    <!-- 测试Spring事件机制 异步发布事件 -->
    <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="5"></property>
    </bean>
    <bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
    	<property name="taskExecutor" ref="taskExecutor"></property>
    </bean>

 

在User1和User2中加入打印当前线程语句。

public void onApplicationEvent(ApplicationEvent event) {
		if(event instanceof XinwenApplicationEvent){
			System.out.println(Thread.currentThread());
			System.out.println("用户2查看新闻");
			System.out.println(event.getSource());
		}
	}

  

测试结果如下



 

如上测试结果可知,两个用户查看新闻是不同线程,即SimpleApplicationEventMulticaster类通过多线程,来实现异步发布事件。

 

源代码如附件

### 事件驱动模型的核心概念 事件驱动模型是一种编程范式,其中程序流由外部事件触发并控制。这种模型广泛应用于现代软件开发中,特别是在需要处理大量异步操作的场景下。它通过定义事件源、监听器和处理器来实现高效的事件分发机制[^1]。 #### 核心组件 - **事件源(Event Source)**:负责生成事件的对象或模块。 - **事件(Events)**:表示状态变化或其他重要行为的数据结构。 - **监听器(Listeners)**:订阅特定类型的事件,并等待通知。 - **处理器(Handlers)**:当接收到对应事件时执行具体逻辑的功能单元。 --- ### Netty中的事件驱动模型实现原理 Netty 是一个高性能的网络应用程序框架,它的事件驱动模型主要依赖于 Reactor 模式。Reactor 模式允许单线程管理多个连接上的 I/O 请求,从而显著提高了资源利用率和系统吞吐量。 以下是其实现的关键点: 1. **Selector 的使用** Java NIO 中的 Selector 被用来监视多个通道的状态变更(如读就绪、写就绪)。Netty 利用这一特性实现了非阻塞式的 I/O 处理[^1]。 2. **ChannelPipeline 和 ChannelHandler** 当数据包到达服务器端口后,会经过一系列预定义好的 `ChannelHandler` 进行处理。这些 Handler 形成了一条链路——即 `ChannelPipeline`,每一步都可以对消息进行拦截、修改或者转发。 3. **线程模型** Netty 支持多种线程配置策略,默认采用 Boss/Worker 线程池模式。Boss 线程专门负责接受新连接;而 Worker 线程则专注于已建立连接的消息读取与发送工作[^1]。 ```java // 创建 EventLoopGroup 并绑定到 ServerBootstrap 上 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new MyCustomHandler()); } }); ``` --- ### Spring Boot中的事件驱动模型实现原理 Spring Boot 对事件驱动的支持基于观察者模式。开发者可以通过自定义 ApplicationEvent 子类创建新的事件类型,并利用 ApplicationContext 提供的方法完成事件发布与消费过程[^2]。 下面是几个重要的组成部分及其作用说明: 1. **ApplicationEvent 类型** 所有用户定义的事件都应继承自该基类。例如,在用户注册完成后可以抛出 UserRegisteredEvent 来告知其他服务采取相应动作。 2. **ApplicationListener 接口** 定义了一个方法 onApplicationEvent() ,任何实现了此接口的 Bean 都会被视为潜在的事件消费者[^2]。 3. **ApplicationContext 发布工具** 使用 AbstractApplicationContext#getApplicationEventMulticaster().multicastEvent(event) 方法即可向整个上下文中广播指定事件实例[^3]。 ```java @Component public class EmailNotificationListener implements ApplicationListener<UserRegisteredEvent> { public void onApplicationEvent(UserRegisteredEvent event) { System.out.println("Sending email to user: " + event.getUserEmail()); } } ``` --- ### 事件驱动模型的应用场景 由于其天然具备良好的解耦能力,因此适合解决那些存在高度交互需求但又希望保持低耦合度的设计目标。典型例子包括但不限于以下几个方面: 1. 用户行为追踪记录; 2. 订单状态更新通知; 3. 实时聊天功能构建; 4. 日志收集分析平台搭建等等。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值