Spring ApplicationEvent 事件


事件机制在一些大型项目中被经常使用,Spring 专门提供了一套事件机制的接口,满足了架构原则上的解耦。

ApplicationContext 通过 ApplicationEvent 类和 ApplicationListener 接口进行事件处理。

如果将实现 ApplicationListener 接口的 bean 注入到上下文中,则每次使用 ApplicationContext 发布 ApplicationEvent 时,都会通知该 bean。

本质上,这是标准的观察者设计模式

使用方法

  • ApplicationContext,Spring 上下文对象,进行事件的发布,发布后通知监听器消费
  • ApplicationEvent,事件对象,可以继承该类并定义消息体
  • ApplicationListener,事件监听器顶层接口,实现该接口来消费消息

1. 定义消息体

/**
 * @author shone
 * @date 2022年07月28日 09:22
 */
public class TestEvent extends ApplicationEvent {
    public TestEvent(Object source) {
        super(source);
    }
}

2. 定义监听器进行消息消费

/**
 * @author shone
 * @date 2022年07月28日 09:26
 */
@Slf4j
@Component
public class TestEventListener implements ApplicationListener<TestEvent> &#123;
    @Override
    public void onApplicationEvent(TestEvent event) &#123;
        log.info("监听器处理事件:&#123;&#125;",event.getSource());
    &#125;
&#125;

注意

需要自定义事件类继承 ApplicationEvent 类,因为 ApplicationEvent 是所有事件的基类,如果监听 ApplicationEvent 类型的任务,Spring 中存在其他的事件发布也会被监听到。

因此需要实现自定义的任务类,并在监听器中使用泛型执行监听任务类型,且发布时发布对应类型的任务。

3. 消息发布

@GetMapping("/test/pushEvent")
public String pushEvent()  &#123;
    log.info("发布事件");
    // 发布Spring事件通知
    SpringUtil.getApplicationContext().publishEvent(new TestEvent("hello event!"));
    return "hello";
&#125;

4. 实现异步消费

定义线程池配置,并在监听器处理任务时指定使用的线程池,如果不指定 Spring 会生产默认类型,即会是同步处理任务。

/**
 * @author shone
 * @date 2022年07月28日 09:45
 */
@Slf4j
@Configuration
public class SpringConfiguration &#123;

    @Bean
    public SimpleApplicationEventMulticaster applicationEventMulticaster(@Qualifier("defaultThreadPoolExecutor") ThreadPoolExecutor defaultThreadPoolExecutor) &#123;
        SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
        simpleApplicationEventMulticaster.setTaskExecutor(defaultThreadPoolExecutor);
        return simpleApplicationEventMulticaster;
    &#125;

    @Bean(name = "defaultThreadPoolExecutor", destroyMethod = "shutdown")
    public ThreadPoolExecutor systemCheckPoolExecutorService() &#123;

        return new ThreadPoolExecutor(3, 10, 60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(10000),
                (r, executor) -> log.error("system pool is full! "));
    &#125;

&#125;

实现原理机制


文章作者: shone
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 shone !
评论
 上一篇
SpringBoot 异步注解 @Async SpringBoot 异步注解 @Async
除了硬编码的异步编程处理方式, SpringBoot 框架还提供了 注解式 解决方案,以 方法体 为边界,方法体内部的代码逻辑全部按异步方式执行。 使用方法@Async 注解使用时需要标注在方法上,来指明当前方法被调用时会异步执行。 需要注
2023-02-02
下一篇 
实现异步消费队列 实现异步消费队列
参考文档:https://blog.csdn.net/u014373554/article/details/109473443 使用阻塞队列+线程池实现异步消费1. 定义任务队列/** * 定义队列 */ private static
2023-02-02 shone
  目录