Spring -- 04 -- ApplicationEvent和Listener的使用

ApplicationEvent 和 Listener 是 Spring 为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者模式,设计初衷在于对系统业务逻辑进行解耦,提高系统的可扩展性以及可维护性


一、Spring 常见内置事件

  • ApplicationContextEvent

    • ApplicationContext 事件发布基类
  • ContextStartedEvent

    • ApplicationContext 启动时发布该事件
  • ContextStoppedEvent

    • ApplicationContext 停止时发布该事件
  • ContextRefreshedEvent

    • ApplicationContext 刷新时发布该事件
  • ContextClosedEvent

    • ApplicationContext 关闭时发布该事件

二、SpringBoot 常见内置事件

  • SpringApplicationEvent

    • SpringApplication 事件发布基类
  • ApplicationStartingEvent

    • SpringApplication 启动时发布该事件

    • 此时应用监听器 (ApplicationListener) 已注册,但应用环境 (Environment) 和应用上下文 (ApplicationContext) 尚未加载

  • ApplicationEnvironmentPreparedEvent

    • SpringApplication 启动时发布该事件

    • 此时,应用环境 (Environment) 已加载,但应用上下文 (ApplicationContext) 尚未加载

  • ApplicationContextInitializedEvent

    • SpringApplication 启动时发布该事件

    • 此时,应用上下文 (ApplicationContext) 已准备好,且应用上下文初始化器 (ApplicationContextInitializers) 已被调用,但 Bean 对象尚未加载

  • ApplicationPreparedEvent

    • SpringApplication 启动时发布该事件

    • 此时,应用上下文 (ApplicationContext) 已准备充分但并未刷新

    • 此阶段 Bean 对象将被加载,且可以使用应用环境 (Environment)

  • ApplicationStartedEvent

    • 刷新应用上下文后发布该事件

    • 此时,尚未调用任何 CommandLineRunner 和 ApplicationRunner 运行器

  • ApplicationReadyEvent

    • 应用程序已准备就绪,并可以处理请求时发布该事件
  • ApplicationFailedEvent

    • SpringApplication 启动失败时发布该事件

三、举例说明

  • MyApplicationEvent 事件,继承自 ApplicationEvent,其 msg 字段为需要发送的消息

    public class MyApplicationEvent extends ApplicationEvent {
    
        private String msg;
    
        public MyApplicationEvent(Object source, String msg) {
            super(source);
            this.msg = msg;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    
  • MsgController 消息控制层

    @RestController
    @RequestMapping("/msg")
    public class MsgController {
    
        @Resource
        private MsgService msgService;
    
        @GetMapping("/send/{msg}")
        public String sendMsg(@PathVariable("msg") String msg) {
            msgService.sendMsg(msg);
            return "Msg sent successfully";
        }
    }
    
  • MsgService 消息业务接口

    public interface MsgService {
    
        void sendMsg(String msg);
    }
    
  • MsgService 消息业务接口实现类,注入 ApplicationContext,负责 MyApplicationEvent 事件的发布

    @Service
    public class MsgServiceImpl implements MsgService {
    
        @Resource
        private ApplicationContext applicationContext;
    
        @Override
        public void sendMsg(String msg) {
            applicationContext.publishEvent(new MyApplicationEvent(this, msg));
        }
    }
    
  • ApplicationListener 监听器,负责监听事件并进行业务流程,共有以下三种实现方式

    1. 使用 @EventListener 注解进行监听

      @Component
      public class MyAnnotationApplicationListener {
      
          @EventListener
          public void receiveMsg(MyApplicationEvent myApplicationEvent) {
              System.out.println("MyAnnotationApplicationListener 接收消息: " + myApplicationEvent.getMsg());
          }
      }
      
    2. 实现 ApplicationListener 接口进行监听

      @Component
      public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
      
          @Override
          public void onApplicationEvent(MyApplicationEvent event) {
              System.out.println("MyApplicationListener 接收消息: " + event.getMsg());
          }
      }
      
    3. 实现 SmartApplicationListener 接口进行监听

      @Component
      public class MySmartApplicationListener implements SmartApplicationListener {
      
          @Override
          public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
              // 只有 MyApplicationEvent 类型的事件才会被监听
              return eventType == MyApplicationEvent.class;
          }
      
          @Override
          public boolean supportsSourceType(Class<?> sourceType) {
              // 只有在 MsgServiceImpl 内发布的 MyApplicationEvent 事件才会被监听
              return sourceType == MsgServiceImpl.class;
          }
      
          @Override
          public void onApplicationEvent(ApplicationEvent event) {
              MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
              System.out.println("MySmartApplicationListener 接收消息: " + myApplicationEvent.getMsg());
          }
      }
      
      • SmartApplicationListener 接口继承自 ApplicationListener 接口

      • SmartApplicationListener 接口并提供了 supportsEventType() 方法和 supportsSourceType() 两个方法用于监听控制,只有这两个方法都返回 true,才会执行 onApplicationEvent() 方法中的监听业务流程

    • 进行测试

      • 在浏览器中请求接口 http://localhost:8080/msg/send/HelloWorld

        image

      • 控制台输出如上所示,三种方式实现了对 MyApplicationEvent 事件的监听

  • 实现 SmartApplicationListener 接口进行有序监听

    • 监听器监听事件是无序的,不过我们可以通过实现 SmartApplicationListener 接口来进行有序监听

    • SmartApplicationListener 接口除了提供了 supportsEventType() 方法和 supportsSourceType() 两个方法用于监听控制,还提供了 getOrder() 方法用于控制事件监听顺序,值越小优先级越高,执行顺序越靠前

    • MyFirstSmartApplicationListener 监听器,监听顺序为 1

      @Component
      public class MyFirstSmartApplicationListener implements SmartApplicationListener {
      
          @Override
          public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
              // 只有 MyApplicationEvent 类型的事件才会被监听
              return eventType == MyApplicationEvent.class;
          }
      
          @Override
          public boolean supportsSourceType(Class<?> sourceType) {
              // 只有在 MsgServiceImpl 内发布的 MyApplicationEvent 事件才会被监听
              return sourceType == MsgServiceImpl.class;
          }
      
          @Override
          public int getOrder() {
              return 1;
          }
      
          @Override
          public void onApplicationEvent(ApplicationEvent event) {
              MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
              System.out.println("MyFirstSmartApplicationListener 接收消息: " + myApplicationEvent.getMsg());
          }
      }
      
    • MySecondSmartApplicationListener 监听器,监听顺序为 2

      @Component
      public class MySecondSmartApplicationListener implements SmartApplicationListener {
      
          @Override
          public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
              // 只有 MyApplicationEvent 类型的事件才会被监听
              return eventType == MyApplicationEvent.class;
          }
      
          @Override
          public boolean supportsSourceType(Class<?> sourceType) {
              // 只有在 MsgServiceImpl 内发布的 MyApplicationEvent 事件才会被监听
              return sourceType == MsgServiceImpl.class;
          }
      
          @Override
          public int getOrder() {
              return 2;
          }
      
          @Override
          public void onApplicationEvent(ApplicationEvent event) {
              MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
              System.out.println("MySecondSmartApplicationListener 接收消息: " + myApplicationEvent.getMsg());
          }
      }
      
    • 进行测试

      • 在浏览器中请求接口 http://localhost:8080/msg/send/HelloWorld

        image

      • 控制台输出如上所示,通过 SmartApplicationListener 接口的 getOrder() 方法实现了对 MyApplicationEvent 事件的有序监听


四、参考资料

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值