• SpringBoot中@EventListener注解的使用


    一:背景
    在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,那就是事件监听,事件监听也是设计模式中发布-订阅模式、观察者模式的一种实现。
    观察者模式:简单的来讲就是你在做事情的时候身边有人在盯着你,当你做的某一件事情是旁边观察的人感兴趣的事情的时候,他会根据这个事情做一些其他的事,但是盯着你看的人必须要到你这里来登记,否则你无法通知到他(或者说他没有资格来盯着你做事情)。
    对于 Spring 容器的一些事件,可以监听并且触发相应的方法。通常的方法有 2 种,ApplicationListener 接口和@EventListener 注解。

    二:简介
    要想顺利的创建监听器,并起作用,这个过程中需要这样几个角色:
    1、事件(event)可以封装和传递监听器中要处理的参数,如对象或字符串,并作为监听器中监听的目标。
    2、监听器(listener)具体根据事件发生的业务处理模块,这里可以接收处理事件中封装的对象或字符串。
    3、事件发布者(publisher)事件发生的触发者。

    三:ApplicationListener 接口
    ApplicationListener 接口的定义如下:

    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
     
    /**
    * Handle an application event.
    * @param event the event to respond to
    */
    void onApplicationEvent(E event);
    }

    它是一个泛型接口,泛型的类型必须是 ApplicationEvent 及其子类,只要实现了这个接口,那么当容器有相应的事件触发时,就能触发 onApplicationEvent 方法。ApplicationEvent 类的子类有很多,Spring 框架自带的如下几个。

    使用方法很简单,就是实现一个 ApplicationListener 接口,并且将加入到容器中就行。

    @Component
    public class MyApplicationListener implements ApplicationListener<ApplicationStartedEvent> {
    
    //    @Override
    //    public void onApplicationEvent(ApplicationEvent event) {
    //        System.out.println("事件触发:"+event.getClass().getName());
    //    }
        @Override
        public void onApplicationEvent(ApplicationStartedEvent event) {
            System.out.println("事件触发:"+event.getClass().getName());
        }
    
    }

    可以看到控制台输出:这样就触发了spring默认的一些事件。

    事件触发:org.springframework.boot.context.event.ApplicationStartedEvent
    事件触发:org.springframework.boot.context.event.ApplicationReadyEvent

    自定义事件以及监听
    定义事件
    首先,我们需要定义一个时间(MyTestEvent),需要继承Spring的ApplicationEvent

    public class MyTestEvent extends ApplicationEvent {
    
        private static final long serialVersionUID = 1L;
    
        private String msg ;
    
        public MyTestEvent(Object source,String msg) {
            super(source);
            this.msg = msg;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    定义监听器
    需要定义一下监听器,自己定义的监听器需要实现ApplicationListener,同时泛型参数要加上自己要监听的事件Class名,在重写的方法onApplicationEvent中,添加自己的业务处理:

    @Component
    public class MyNoAnnotationListener implements ApplicationListener<MyTestEvent> {
    
        @Override
        public void onApplicationEvent(MyTestEvent event) {
            System.out.println("非注解监听器:" + event.getMsg());
        }
    
    }

    事件发布
    有了事件,有了事件监听者,那么什么时候触发这个事件呢?每次想让监听器收到事件通知的时候,就可以调用一下事件发布的操作。首先在类里自动注入了ApplicationEventPublisher,这个也就是我们的ApplicationCOntext,它实现了这个接口。

    @RestController
    @RequestMapping("testEventController")
    public class MyTestEventController {
    
        @Autowired
        private ApplicationEventPublisher applicationEventPublisher;
    
        @RequestMapping(value = "/testPublishEvent1" )
        public void testPublishEvent(){
            applicationEventPublisher.publishEvent(new MyTestEvent(this, "我来了"));
        }
    
    }

    输出结果如下图所示:

    非注解监听器:我来了

    四:@EventListener 注解
    简单使用
    除了通过实现接口,还可以使用@EventListener 注解,实现对任意的方法都能监听事件。
    在任意方法上标注@EventListener 注解,指定 classes,即需要处理的事件类型,一般就是 ApplicationEven 及其子类,可以设置多项。

    @Configuration
    public class Config {
    
        @EventListener(classes = {SpringApplicationEvent.class})
        public void listen(SpringApplicationEvent event) {
            System.out.println("注解事件触发:" + event.getClass().getName());
        }
    
    }

    启动项目
    可以看到控制台和之前的输出是一样的:

    注解事件触发:org.springframework.boot.context.event.ApplicationStartedEvent
    注解事件触发:org.springframework.boot.context.event.ApplicationReadyEvent

    自定义事件以及监听
    使用注解的好处是不用每次都去实现ApplicationListener,可以在一个class中定义多个方法,用@EventListener来做方法级别的注解。
    和上面类似,事件以及事件发布不需要改变,只要这样定义监听器即可。

    此时,就可以有一个发布,两个监听器监听到发布的消息了,一个是注解方式,一个是非注解方式
    结果:

    注解监听器----1:我来了
    非注解监听器:我来了

    总结
    上面介绍了@EventListener的原理,其实上面方法里还有一个@TransactionalEventListener注解,其实原理是一模一样的,只是这个监听者可以选择在事务完成后才会被执行,事务执行失败就不会被执行。
    这两个注解的逻辑是一模一样的,并且@TransactionalEventListener本身就被标记有@EventListener,
    只是最后生成监听器时所用的工厂不一样而已。

    郭慕荣博客园
  • 相关阅读:
    nes 红白机模拟器 第4篇 linux 手柄驱动支持
    nes 红白机模拟器 第3篇 游戏手柄测试 51 STM32
    nes 红白机模拟器 第2篇 InfoNES
    python语言输入
    python控制窗口口字形运动
    python控制窗口对角线运动
    python控制窗口移动(画圆)
    python控制窗口缩放
    python控制窗口显示隐藏
    python修改内存,(修改植物大战僵尸)
  • 原文地址:https://www.cnblogs.com/jelly12345/p/14763653.html
Copyright © 2020-2023  润新知