springboot监听器的使用(ApplicationListener、SmartApplicationListener、@EventListener)

这篇具有很好参考价值的文章主要介绍了springboot监听器的使用(ApplicationListener、SmartApplicationListener、@EventListener)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

监听器: 当某个事件触发的时候,就会执行的方法块。

springboot提供了两个接口来实现监听:ApplicationListenerSmartApplicationListener,如下图。显而易见,SmartApplicationListenerApplicationListener 的子类,故而其功能要强于 ApplicationListener
applicationlistener,Spring Boot,spring boot,listener
applicationlistener,Spring Boot,spring boot,listener

当然,springboot很贴心地提供了一个 @EventListener 注解来实现监听。

1. ApplicationListener

1. 简单的全局监听

首先,先来简单体验一下监听器的功能。

需求: 在spring容器初始化完成之后就开始监听,并打印日志。

实现:

  • 准备springboot工程(依赖:springboot、lombok)

  • 写一个监听器

    @Slf4j
    @Component
    public class MyTask implements ApplicationListener<ContextRefreshedEvent> {
    
        private static boolean aFlag = false;
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            if (!aFlag) {
                aFlag = true;
                log.info("我已经监听到了");
            }
        }
    }
    
  • 启动项目,控制台输出如下:
    applicationlistener,Spring Boot,spring boot,listener

现在来说一下为什么要这么写监听器:

  • 实现接口

    implements ApplicationListener<ContextRefreshedEvent>
    

    自定义监听器需要实现 ApplicationListener<E extends ApplicationEvent> 接口

    ContextRefreshedEvent 是一个事件,它会在 spring容器初始化完成 之后被触发,所以监听器就会在 spring容器初始化完成之后开始监听,所以这就是所谓的全局监听

  • 标志位 aFlag

    private static boolean aFlag = false;
    

    aFlag 是一个启动标志
    因为web应用会出现父子容器,这样就会触发两次监听任务,所以需要一个标志位,保证监听任务(log.info(“我已经监听到了”))只会触发一次

2. 定时任务

需求: 实现一个定时任务,每间隔5秒、10秒、15秒、20秒、25秒、30秒、40秒、50秒、60秒,在控制台打印一次日志。

实现: 可通过多线程的方式实现

  • 新建一个类 TimerRunner 继承 Runnable

  • 5秒到60秒的间隔可以通过 枚举类实现

    private enum TimerEnum {
        // 第5秒打印
        FIRST(1, 5 ),
        // 第10秒打印
        SECOND(2, 10),
        // 第15秒打印
        THIRD(3, 15),
        // 第20秒打印
        FOURTH(4, 20),
        // 第25秒打印
        FIFTH(5, 25),
        // 第30秒打印
        SIXTH(6, 30),
        // 第40秒打印
        SEVENTH(7, 40),
        // 第50秒打印
        EIGHTH(8, 50),
        // 第60秒打印
        NINTH(9, 60);
    
        private Integer count;
    
        private Integer time;
    
        TimerEnum(Integer count, Integer time) {
            this.count = count;
            this.time = time;
        }
    
        public Integer getCount() {
            return count;
        }
    
        public Integer getTime() {
            return time;
        }
    }
    
  • TimeRunner 完整代码

    @Slf4j
    public class TimerRunner implements Runnable{
        @Override
        public void run() {
            // 打印次数
            int count = 1;
            SimpleDateFormat dateFormat= new SimpleDateFormat("hh:mm:ss");
            for (TimerEnum item: TimerEnum.values()) {
                if (count == item.getCount()) {
                    if (count != 9) {
                        log.info("时间: " + dateFormat.format(new Date()) + "第 " + count + " 次打印,还剩余 " + (9 - count) + " 次完成打印");
                        count++;
                    } else {
                        log.info("最后一次打印");
                        log.info("已完成所有打印任务!");
                    }
                }
                try {
                	// TimeUnit来sleep,可读性更好
                    TimeUnit.SECONDS.sleep(item.getTime());
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    
        private enum TimerEnum {
            // 第5秒打印
            FIRST(1, 5 ),
            // 第10秒打印
            SECOND(2, 10),
            // 第15秒打印
            THIRD(3, 15),
            // 第20秒打印
            FOURTH(4, 20),
            // 第25秒打印
            FIFTH(5, 25),
            // 第30秒打印
            SIXTH(6, 30),
            // 第40秒打印
            SEVENTH(7, 40),
            // 第50秒打印
            EIGHTH(8, 50),
            // 第60秒打印
            NINTH(9, 60);
    
            private Integer count;
    
            private Integer time;
    
            TimerEnum(Integer count, Integer time) {
                this.count = count;
                this.time = time;
            }
    
            public Integer getCount() {
                return count;
            }
    
            public Integer getTime() {
                return time;
            }
        }
    }
    
  • MyTask 代码

    @Slf4j
    @Component
    public class MyTask implements ApplicationListener<ContextRefreshedEvent> {
    
        private static boolean aFlag = false;
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            if (!aFlag) {
                aFlag = true;
                new Thread(new TimerRunner()).start();
            }
        }
    }
    
  • 控制台输出:
    applicationlistener,Spring Boot,spring boot,listener

3. 监听自定义事件

Spring的 ApplicationContext 提供了支持事件和代码中监听器的功能。
我们可以创建bean用来监听在 ApplicationContext 中发布的事件。ApplicationEvent 类在 ApplicationContext 接口中处理的事件,如果一个bean实现了 ApplicationListener 接口,当一个 ApplicationEvent 被发布以后,bean会自动被通知。


参考链接:https://cloud.tencent.com/developer/article/1532994

applicationlistener,Spring Boot,spring boot,listener

先来看一下 spring的内置事件

内置事件: 参考链接: https://blog.csdn.net/liyantianmin/article/details/81017960

事件 说明
ContextRefreshedEvent ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。
ContextStartedEvent 当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
ContextStoppedEvent 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
ContextClosedEvent 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
RequestHandledEvent 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。

自定义监听事件:

  • extends ApplicationEvent 自定义事件

    public class MyEvent extends ApplicationEvent {
    
        private String time = new SimpleDateFormat("hh:mm:ss").format(new Date());
        private String msg;
    
        public MyEvent(Object source, String msg) {
            super(source);
            this.msg = msg;
        }
    
        public MyEvent(Object source) {
            super(source);
        }
    
        public String getTime() {
            return time;
        }
    
        public void setTime(String time) {
            this.time = time;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    
  • 监听器

    @Slf4j
    @Component
    public class MyTask implements ApplicationListener {
    
        private static boolean aFlag = false;
    
    
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof ContextRefreshedEvent) {
                log.info("监听到 ContextRefreshedEvent...");
            }
            if (event instanceof MyEvent) {
                log.info("监听到 MyEvent...");
                MyEvent myEvent = (MyEvent) event;
                System.out.println("时间:" + myEvent.getTime() + " 信息:" + myEvent.getMsg());
            }
        }
    }
    
  • 触发事件
    自定义监听事件需要主动触发

    @SpringBootApplication
    public class TaskApplication {
        public static void main(String[] args) {
            ConfigurableApplicationContext run = SpringApplication.run(TaskApplication.class, args);
            MyEvent event = new MyEvent("event", "忙中岁月忙中遣,我本愚来性不移");
            // 发布事件
            run.publishEvent(event);
        }
    }
    

    也可以这样触发,美观一点

    @SpringBootApplication
    public class TaskApplication implements CommandLineRunner {
        public static void main(String[] args) {
            SpringApplication.run(TaskApplication.class, args);
        }
    
        @Resource
        private ApplicationContext applicationContext;
    
        @Override
        public void run(String... args) throws Exception {
            MyEvent event = new MyEvent("event", "忙中岁月忙中遣,我本愚来性不移");
            // 发布事件
            applicationContext.publishEvent(event);
    
        }
    }
    
  • 控制台输出
    applicationlistener,Spring Boot,spring boot,listener

2. SmartApplicationListener

1. 简单使用

@Slf4j
@Component
public class MyTask implements SmartApplicationListener {
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == MyEvent.class || eventType == ContextRefreshedEvent.class;
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            log.info("监听到 ContextRefreshedEvent...");
        }
        if (event instanceof MyEvent) {
            log.info("监听到 MyEvent...");
            MyEvent myEvent = (MyEvent) event;
            System.out.println("时间:" + myEvent.getTime() + " 信息:" + myEvent.getMsg());
        }
    }
}
applicationlistener,Spring Boot,spring boot,listener

2. 方法介绍

public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {

	boolean supportsEventType(Class<? extends ApplicationEvent> eventType);

	default boolean supportsSourceType(@Nullable Class<?> sourceType) {
		return true;
	}

	@Override
	default int getOrder() {
		return LOWEST_PRECEDENCE;
	}

	default String getListenerId() {
		return "";
	}

}
方法 说明
supportsEventType 确认当前监听器是否支持当前事件类型。
supportsSourceType 确定此监听器是否实际支持给定的源类型。
getOrder 确定此侦听器在同一事件的一组侦听器中的顺序。数值越小,优先级越高。
getListenerId 返回侦听器的可选标识符。

3. @EventListener

使用:

@Slf4j
@Component
public class MyTask {
    @EventListener
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            log.info("监听到 ContextRefreshedEvent...");
        }
        if (event instanceof MyEvent) {
            log.info("监听到 MyEvent...");
            MyEvent myEvent = (MyEvent) event;
            System.out.println("时间:" + myEvent.getTime() + " 信息:" + myEvent.getMsg());
        }
    }
}
@Slf4j
@Component
public class MyTask {
    @EventListener
    public void MyEventListener(MyEvent event) {
        log.info("监听到 MyEvent...");
        MyEvent myEvent = (MyEvent) event;
        System.out.println("时间:" + myEvent.getTime() + " 信息:" + myEvent.getMsg());
    }

    @EventListener
    public void ContextRefreshedEventListener(MyEvent event) {
        log.info("监听到 ContextRefreshedEvent...");
    }
}

指定监听事件的类型:文章来源地址https://www.toymoban.com/news/detail-791580.html

@EventListener(MyEvent.class)

@EventListener({MyEvent.class, ContextRefreshedEvent.class})

到了这里,关于springboot监听器的使用(ApplicationListener、SmartApplicationListener、@EventListener)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot2.0(过滤器,监听器,拦截器)

    使用Servlet3.0的注解进行配置 启动类里面增加 @ServletComponentScan ,进行扫描 新建一个Filter类,implements Filter ,并实现对应接口 @WebFilter 标记一个类为Filter,被spring进行扫描 urlPatterns:拦截规则,支持正则 控制chain.doFilter的方法的调用,来实现是否通过放行, 不放行的话,web应用

    2024年02月07日
    浏览(42)
  • 207、SpringBoot 整合 RabbitMQ 实现消息的发送 与 接收(监听器)

    1、ContentUtil 先定义常量 2、RabbitMQConfig 创建队列的两种方式之一: 配置式: 在容器中配置 org.springframework.amqp.core.Queue 类型的Bean,RabbitMQ将会自动为该Bean创建对应的队列。 就是在配置类中创建一个生成消息队列的@Bean。 问题: 用 @Configuration 注解声明为配置类,但是项目启动

    2024年02月06日
    浏览(57)
  • Vue3监听器使用

    watch(监听的对象或值, 回调函数(参数新值,旧值), 配置项是对象={   immediate: true//立即监听--进入就会执行一次 deep:true //深度监听 }) 首先引入 设置响应式数据 设置点击事件,点击触发修改num 监听简单数据类型----- immediate: true//立即监听--进入就会执行一次 ---------------

    2024年02月07日
    浏览(44)
  • Flutter中的AppLifecycleListener:应用生命周期监听器介绍及使用

    引言 当你在Flutter中需要监听应用程序的生命周期变化时,可以使用 AppLifecycleListener 。在Flutter 3.13中, AppLifecycleListener 被添加到Framework中,用于监听应用程序的生命周期变化,并响应退出应用程序的请求等支持。 在Flutter 3.13之前,我们通常使用 WidgetsBindingObserver 的 didChange

    2024年01月20日
    浏览(50)
  • JMeter关于influxDB 2.x 后端监听器使用

    目前大部分资料都是介绍有关 jmeter 与 influxdb1.x 版本的集成,但是,在 2021 年,influxdb 升级到 2.x 版本,这个版本与 1.x 版本有结构性的调整,完全不兼容,直接要切换过来难度不小,官网和社区这方面的资料也不多,所以我边用边做个笔记,方便自我查阅,有需要的人也可

    2023年04月10日
    浏览(36)
  • Unity UGUI的EventTrigger (事件监听器)组件的介绍及使用

    EventTrigger是Unity UGUI中的一个组件,用于监听和响应UI元素的各种事件,例如点击、拖拽、进入、离开等。通过EventTrigger组件,我们可以方便地为UI元素添加各种交互行为。 EventTrigger组件通过监听UI元素上的事件,并在事件触发时执行相应的回调函数。每个UI元素可以添加多个

    2024年02月15日
    浏览(53)
  • HttpSessionListener监听器和HttpSessionAttributeListener监听器

    1.作用:监听Session创建或销毁,即生命周期监听 2.相关方法: 3.使用场景: 和前面的ServletContextListener等一样,可以用于监控用户上线和离线 4.代码 HttpSessionListener监听器 实现类 HttpSessionAttributeListener监听器 1.作用:监听Session属性的变化,使用少 2.相关方法: 3.代码 监听器 实

    2024年02月04日
    浏览(51)
  • camunda执行监听器和任务监听器有什么区别

    Camunda的执行监听器和任务监听器是用于添加自定义逻辑的监听器,它们的区别在于作用对象和触发事件的不同。 执行监听器是与BPMN流程中的各种流程元素(例如开始事件、用户任务、服务任务、网关等)相关联的。执行监听器可以在流程元素执行前、执行后或抛出异常时添

    2024年02月04日
    浏览(56)
  • Listener监听器----HttpServletRequest对象的生命周期监听器

    一、HttpServletRequest对象的生命周期监听器         ServletRequestListener接口定义了ServletRequest(是HttpServletRequest接口的父接口类型)对象生命周期的监听行为。 void requestInitialized(ServletRequestEvent sre)         HttpServletRequest对象创建后会触发该监听器方法,并将已创建HttpServletR

    2024年01月23日
    浏览(61)
  • 消息监听器和消息监听容器

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 消息监听器顾名思义用来接收消息,它是使用消息监听容器的必须条件。目前有8个消息监听器: 使用自动提交或容器管理的提交方法之一,处理从 Kafka 消费者 p

    2024年02月07日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包