Spring boot Enent实现事件发布订阅

文章详细介绍了Spring框架中基于观察者模式的事件监听机制,包括事件(Event)、事件源(EventSource)、事件监听器(EventListener)的角色以及如何发布和处理事件。通过ApplicationEventPublisher接口触发事件,并展示了如何通过实现ApplicationEventListener接口或使用@EventListener注解来定义事件监听器。此外,还讨论了如何配置监听器进行异步执行,以及通过线程池控制异步任务的执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring中的事件监听机制是运用观察者模式来实现

  • 观察者模式的优点有:

    1、观察者和被观察者之间低耦合,代码比较好维护

    2、被观察者和观察者之间是一对多Q的关系(当然也可以一对一),当被观察者状态改变的时候,多个观察者能同时进行处理,能实现广播通讯

  • 观察者模式Q有两种角色:

    1、Subject目标角色:接收外界的状态变化,向观察者发送通知(广播通知)

    2、Observer观察者角色:观察Subject状态变化,触发具体操作罗辑

    所以说subject和observer之间是一对多的关系


事件驱动模型三大要素:

  • 事件(Event Object) :用户交互行为产生的一种效果 (鼠标事件、键盘事件、窗口事件)
  • 事件源(Event Source) :触发事件的源头,不同的事件源会触发不同的事件
  • 事件监听器(Event lisrener) :负责监听事件源发出的各种事件

事件生产者:发布事件、触发事件。

  • 实现已经封装好的ApplicationEventPublisherAware接口
@Component
public class EventService implements ApplicationEventPublisherAware {
    public ApplicationEventPublisher applicationEventPublisher;

    @Override
    public void setApplicationEventPublisher(@NotNull ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    //触发事件,也可以添加注解@Async进行异步处理
    @Async
    public CompletableFuture<Boolean> doEvent(EventObj o) {
        applicationEventPublisher.publishEvent(o);
        return CompletableFuture.completedFuture(Boolean.TRUE);
    }


}
  • 也可以直接进行发布

@SpringBootTest
public class PubsubTest {    
  @Autowired    
  private ApplicationEventPublisher publisher;
  
  Message message = Message.builder()
                    .key("123")            
                    .msgId(11111)            
                    .build();     
  @Test    
  void testProducer(){        
          System.out.println("执行业务代码...");        
          publisher.publishEvent(new MessageProducerEvent(message));   
  }
  
}

事件主体

  • 承载事件主体内容的类需要继承ApplicationEvent后,通过其构造方法设置事件主体所携带的事件内容或者说是发布物类型,一个主体可以承载多个事件主体内容
/**
 * 事件主体
 */

public class EventObj extends ApplicationEvent {

    private static final long serialVersionUID = -3917128390492677860L;

  /**
   *事件内容一
   */
    public EventObj(EventText source) {
        super(source);
    }
    
  /**
   *事件内容二
   */
    public EventObj(EventSon source) {
        super(source);
    }
}
  • 或者增加泛型扩展适配
/**
 * 事件主体
 */

public class EventObj<T> extends ApplicationEvent {

    private static final long serialVersionUID = -3917128390492677860L;

    public EventObj(T source) {
        super(source);
    }
}

事件内容

事件内容,其属性就是事件发生的内容数据

@Data
public class EventSon {

    private String eventValue;

    public EventSon(String eventValue) {
        this.eventValue = eventValue;
    }
}

事件监听者(订阅者)

事件响应者一般有两种实现方式,一种是实现ApplicationEvevListener接口,另一种是使用注解@EventListener

  • 实现ApplicationEvevListener接口
    • 可以使用泛型也可以直接用自己定义的事件主体
    /**
     * 监听器组件
     */
    @Component
    public class EventLinstener <T extends ApplicationEvent> implements ApplicationListener<T> {
    
        @Override
        public void onApplicationEvent(T event) {
            //响应事件处理的业务代码
        }
    }
    
  • 使用注解@EventListener
    • value:监听的事件主体
    • id:标识,多个监听器顺序执行
    • condition:自定义处理,例如:condition = “myEventPredicate.test(#obj)”
    /**
     * 监听器组件
     */
    @Component
    public class EventLinstener  {
    
        /**
         * 注册监听器1内容
         *
         * @return
         */
        @EventListener
        public Boolean eventListener0(EventObj<EventSon> obj) {
            System.out.println("零监听到事件:" + obj.getSource());
            return Boolean.TRUE;
        }
        /**
         * 注册监听器1内容
         *
         * @return
         */
        @EventListener(value = EventObj.class)
        public Boolean eventListener1(EventObj<EventSon> obj) {
            System.out.println("一监听到事件:" + obj.getSource());
            return Boolean.TRUE;
        }
    
        /**
         * 注册监听器2内容
         *
         * @return
         */
        @EventListener(id = "eventObj2",value = EventObj.class)
        public Boolean eventListener2(EventObj<EventText> obj) {
            System.out.println("二监听到事件:" + obj.getSource());
            return Boolean.TRUE;
        }
    
        /**
         * 注册监听器3内容,自定义监听器匹配机制
         *
         * @return
         */
        @EventListener(id = "eventObj3",value = EventObj.class,condition = "myEventPredicate.test(#obj)")
        public Boolean eventListener3(EventObj obj) {
            System.out.println("三监听到事件:" + obj.getSource());
            return Boolean.TRUE;
        }
    
        /**
         * 注册监听器4内容,自定义监听器匹配机制
         *
         * @return
         */
        @EventListener(id = "eventObj4",value = EventObj.class,condition = "myEventPredicate.test(#obj)")
        public Boolean eventListener3(EventObj obj) {
            System.out.println("四监听到事件:" + obj.getSource());
            return Boolean.TRUE;
        }
    
    }
    
  • 由于多个监听器可以监听一个事件,所以可以自定义的监听器匹配机制
    /**
     * 可以增加断言,来判断当事件发生时,监听器是否会触发
     */
    @Component
    public class MyEventPredicate <T> implements Predicate<EventObj<T>> {
        @Override
        public boolean test(EventObj<T> eventObj) {
            //增加判断的逻辑,决定一个事件由哪一个监听器执行
            return false;
        }
    }
    
    ------------------
        /**
         * 注册监听器3内容,自定义监听器匹配机制
         *
         * @return
         */
        @EventListener(id = "eventObj3",value = EventObj.class,condition = "myEventPredicate.test(#obj)")
        public Boolean eventListener3(EventObj obj) {
            System.out.println("三监听到事件:" + obj.getSource());
            return Boolean.TRUE;
        }
    
        /**
         * 注册监听器4内容,自定义监听器匹配机制
         *
         * @return
         */
        @EventListener(id = "eventObj4",value = EventObj.class,condition = "myEventPredicate.test(#obj)")
        public Boolean eventListener3(EventObj obj) {
            System.out.println("四监听到事件:" + obj.getSource());
            return Boolean.TRUE;
        }
    

配置监听器异步执行

  • 创建事件广播配置为异步
/**
 * 配置所有的监听器异步执行
 */
@Configuration
public class ApplicationEventAsyncConfig {
    @Resource
    private ThreadPoolTaskExecutor myExecutor;

    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster() {
        //创建一个事件广播器
        SimpleApplicationEventMulticaster result = new SimpleApplicationEventMulticaster();
        //设置异步执行器,来完成异步执行监听事件这样会导致所有的监听器都异步执行
        result.setTaskExecutor(myExecutor);
        return result;
    }
}
  • 配置线程池
     /**
      * 异步的线程池
      */
    @Configuration
    publicclass ThreadPoolTaskConfig {
            @Bean("myExecutor")
            public Executor taskExecutor() {
                ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
                //设置线程池参数信息
                taskExecutor.setCorePoolSize(8);
                taskExecutor.setMaxPoolSize(20);
                taskExecutor.setQueueCapacity(50);
                taskExecutor.setKeepAliveSeconds(60);
                taskExecutor.setThreadNamePrefix("eventHandle--");
                taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
                //设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。
                taskExecutor.setAwaitTerminationSeconds(60);
                //修改拒绝策略为使用当前线程执行
                taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
                //初始化线程池
                taskExecutor.initialize();
                return taskExecutor;
            }
        }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值