事件驱动

222 阅读2分钟

所谓事件驱动就是借助观察者模式,在事件发生时,所有的监听器都会监听到这个事件,从而对事件的源做出相应的处理。 Spring 的事件驱动模型由三部分组成: 事件(Event)、事件发布者(EventPublisher)、事件监听器(Listener)

事件驱动是通过 ApplicationContext 实现的: 容器启动时,将继承了 ApplicationListener 的类装载到 ApplicationContext 中实现的一个 Set 中。

通过注解 @EventListener 可以实现方法级的监听器 他通过 EventListenerMethodProcessor 注册到容器中,该类定义了一个 Bean,在初始化完成后,调用它的后置回调方法,在方法中遍历容器中所有的 Bean,将用注解修饰的方法根据参数创建 ApplicationListener 对象加入到 ApplicationContext 监听集合中。

继承了 ApplicationEvent 的对象都可以作为事件发布,Application 中包含了数据源和事件发布的时间。

事件的发布者范围比较宽泛,只要是使用 ApplicationContext#publishEvent 的对象,都可以称作事件的发布者。

ApplicationContext 中包含一个实现 ApplicationEventMulticaster 接口的对象,默认实现的是 SimpleApplicationEventMulticaster,它仅提供了最常用的事件操作。在发布事件后,会调用 SimpleApplicationEventMulticaster#multicastEvent 方法,遍历 invoke 集合中所有监听器的处理方法。

Spring 处理事件是同步的,如果监听者执行的时间过长,反映出来的就可能是响应时间过长。 如果事件的处理一定或者可能会带来较长的等待时间,那么可以选择异步处理。

@Async、@EnableAsync

@EnableAsync 注解是用来开启 Spring 的异步功能的,在方法上加上 @Async 注解,就可以让这个方法变成一个异步方法。 Spring 的异步方法主要是通过 Spring AOP 和线程池实现的,当对某个类的一个方法加上 @Async 注解时,就会生成这个类的一个增强类。这个类重写了这个方法,使得调用这个方法时,是将这个方法作为 task 交给线程池去执行,从而实现异步。

在 EventListener#onApplicationEvent 方法上使用 @Async 方法,就可以对事件进行异步处理。

@Async
public void onApplicationEvent(ApplicationEvent event) { ...; }

除此之外,还可以通过实现 AsyncConfigurer 指定线程池和异常处理程序

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

		@Override
		public Executor getAsyncExecutor() {
				return new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), r -> new Thread(r, "Async Task"));
		}

		@Override
		public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
				return new SimpleAsyncUncaughtExceptionHandler();
		}

}