springboot实战原理(10)--配置事件监听的4种方式和原理

简介: springboot实战原理(10)--配置事件监听的4种方式和原理

目录:


1dc618a0ed9580ce8bfa6facb208c08f.png


一、配置监听器的步骤:


1.自定义事件,一般是继承ApplicationEvent抽象类

2定义事件监听器,一般是实现ApplicationListener的接口

3.启动时候,需要把监听器加入到spring容器中

4.发布事件,使用ApplicationEventPublisher.publishEvent 发布事件


二、配置监听器:4种方式:


①SpringApplication…addListeners增加


例子:

//定义事件
//定义事件
public class MyAplicationEvent extends ApplicationEvent {
    private static final long serialVersionUID = 1L;
    public MyAplicationEvent(Object source) {
        super(source);
    }
}


//监听器
public class MyApplicationListener implements ApplicationListener<MyAplicationEvent> {
    @Override
    public void onApplicationEvent(MyAplicationEvent event) {
        System.out.println("接受到事件============"+ event.getClass());
    }
}


//在启动入口中:通过addListeners增加添加到spring容器和发布事件
@SpringBootApplication
public class Demo7Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo7Application.class);
        //addListeners增加
        app.addListeners(new MyApplicationListener());
        ConfigurableApplicationContext context = app.run(args);
        //发布事件
        context.publishEvent(new MyAplicationEvent(new Object()));
        context.close();
//        context.stop();
    }
}


运行结果:


5d4c6812c8535adbb050f4ddf2e1bce8.png

显示监听器已经注入。


② 使用@Component 把监听器纳入到spring容器中管理


修改刚才的代码:我们在监听器上加上@Component


//监听器
@Component
public class MyApplicationListener implements ApplicationListener<MyAplicationEvent> {
    @Override
    public void onApplicationEvent(MyAplicationEvent event) {
        System.out.println("接受到事件============"+ event.getClass());
    }
}


入口函数删除 addListener


@SpringBootApplication

public class Demo7Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo7Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyAplicationEvent(new Object()));
        context.close();
//        context.stop();
    }
}


重新运行代码:

1dc618a0ed9580ce8bfa6facb208c08f.png

也说明,监听器生效了。


③ application.properties中配置context.listener.classes属性


配置如下: context.listener.classes=com.springboot.demo7.MyApplicationListener

5d4c6812c8535adbb050f4ddf2e1bce8.png


入口函数不变,继续运行:


@SpringBootApplication
public class Demo7Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo7Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyAplicationEvent(new Object()));
        context.close();
//        context.stop();
    }
}


同样,监听器生效:


1dc618a0ed9580ce8bfa6facb208c08f.png


④使用注解 @EventListener


我们定义一个MyEventHandle监听器处理类, 使用注解 @EventListener,在方法上面加入@EventListener注解,且该类需要纳入到spring容器中管理。

看代码:


@Component
public class MyEventHandle {
    /*
     * 任意参数
     * 所有,该参数事件,或者其子事件都可以接收到
     * @param event  任意参数
     */
    @EventListener
    public void onApplicationEvent(MyAplicationEvent event) {
        System.out.println("接受到事件============"+ event.getClass());
    }
}


运行:


@SpringBootApplication
public class Demo7Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo7Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyAplicationEvent(new Object()));
        context.close();
//        context.stop();
    }
}


5d4c6812c8535adbb050f4ddf2e1bce8.png

5d4c6812c8535adbb050f4ddf2e1bce8.png

依然注入进来了。


这里可以修改

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


如果改成Object,就表示任意参数,所有,该参数事件,或者其子事件都可以接收到。


@Component
public class MyEventHandle {
    /*
     * 任意参数
     * 所有,该参数事件,或者其子事件都可以接收到
     * @param event  任意参数
     */
    @EventListener
    public void onApplicationEvent(Object event) {
        System.out.println("接受到事件============"+ event.getClass());
    }
 }


运行:


@SpringBootApplication
public class Demo7Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo7Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyAplicationEvent(new Object()));
        context.close();
//        context.stop();
    }
}

1dc618a0ed9580ce8bfa6facb208c08f.png

可以看到,不过有我们自定义的事件,spring默认注入的事件都打印出来了。


三、原理


第一二种方式都是启动时候,把监听器加入到spring容器中,ConfigurableApplicationContext拿到这个对象再发布就可使用监听器了。

第三四中最终也是吧监听器ConfigurableApplicationContext,只不过实现有了2个特别的类:


①context.listener.classes配置原理之DelegatingApplicationListener:


看下源码


1dc618a0ed9580ce8bfa6facb208c08f.png

5d4c6812c8535adbb050f4ddf2e1bce8.png46a9d80a6e05e4e3b19d57a0ee70bcdf.png


我们可以看到,这个类是读取了配置的属性context.listener.classes,加入到监听器列表并序好给我们的spring容器。


② 注解@EventListener配置原理之 EventListenerMethodProcessor


看名字就知道EventListenerMethodProcessor这个是个后置处理器:

看下源码:

66ba272a0bfc97be54a5fa679e3d5482.png


afterSingletonsInstantiated方法调用了processBean方法:

processBean方法获取所有的@EventListener的注解:

1dc618a0ed9580ce8bfa6facb208c08f.png

该方法有这些注解的类加入到了context中,Springboot就可以使用了。

5d4c6812c8535adbb050f4ddf2e1bce8.png


四、spring和springboot默认自定义的事件查看


他们都在context包下:


看下springboot下的很多默认的事件和监听器

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


看下spring5下的很多默认的事件和监听器:


66ba272a0bfc97be54a5fa679e3d5482.png


五、测试下默认的监听器:


我们测试下spring提供的:

1dc618a0ed9580ce8bfa6facb208c08f.png


我们使用第4种方式测试下:


@Component
public class MyEventHandle {
    @EventListener
    public void event2(ContextStoppedEvent event) {
        System.out.println("应用停止事件============"+ event.getClass());
    }
}


@SpringBootApplication
public class Demo7Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo7Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.stop();
    }
}


看下打印结果:

1dc618a0ed9580ce8bfa6facb208c08f.png

说明这个应用关闭的事件触发了。


总结:本文章主要讲了springboot配置监听器的步骤方式,原理和自带的事件等。


相关文章
|
2月前
|
Java Spring
Spring boot 运行服务jar外配置配置文件方式总结
Spring boot 运行服务jar外配置配置文件方式总结
461 0
|
4天前
|
Java 应用服务中间件 API
Vertx高并发理论原理以及对比SpringBoot
Vertx 是一个基于 Netty 的响应式工具包,不同于传统框架如 Spring,它的侵入性较小,甚至可在 Spring Boot 中使用。响应式编程(Reactive Programming)基于事件模式,通过事件流触发任务执行,其核心在于事件流 Stream。相比多线程异步,响应式编程能以更少线程完成更多任务,减少内存消耗与上下文切换开销,提高 CPU 利用率。Vertx 适用于高并发系统,如 IM 系统、高性能中间件及需要较少服务器支持大规模 WEB 应用的场景。随着 JDK 21 引入协程,未来 Tomcat 也将优化支持更高并发,降低响应式框架的必要性。
Vertx高并发理论原理以及对比SpringBoot
|
2月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
99 0
|
1天前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
15天前
|
Java 开发者 数据格式
【Java笔记+踩坑】SpringBoot基础4——原理篇
bean的8种加载方式,自动配置原理、自定义starter开发、SpringBoot程序启动流程解析
【Java笔记+踩坑】SpringBoot基础4——原理篇
消息中间件 缓存 监控
75 0
|
26天前
|
IDE Java 开发工具
还在为繁琐的配置头疼吗?一文教你如何用 Spring Boot 快速启动,让开发效率飙升,从此告别加班——打造你的首个轻量级应用!
【9月更文挑战第2天】Spring Boot 是一款基于 Spring 框架的简化开发工具包,采用“约定优于配置”的原则,帮助开发者快速创建独立的生产级应用程序。本文将指导您完成首个 Spring Boot 项目的搭建过程,包括环境配置、项目初始化、添加依赖、编写控制器及运行应用。首先需确保 JDK 版本不低于 8,并安装支持 Spring Boot 的现代 IDE,如 IntelliJ IDEA 或 Eclipse。
81 5
|
1月前
|
安全 前端开发 Java
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
在Web安全上下文中,源(Origin)是指一个URL的协议、域名和端口号的组合。这三个部分共同定义了资源的来源,浏览器会根据这些信息来判断两个资源是否属于同一源。例如,https://www.example.com:443和http://www.example.com虽然域名相同,但由于协议和端口号不同,它们被视为不同的源。同源(Same-Origin)是指两个URL的协议、域名和端口号完全相同。只有当这些条件都满足时,浏览器才认为这两个资源来自同一源,从而允许它们之间的交互操作。
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
|
1月前
|
缓存 前端开发 Java
"揭秘!SpringBoot携手Nginx,性能飙升秘籍大公开:轻松掌握配置优化,让你的应用快如闪电!"
【8月更文挑战第11天】随着微服务架构的发展,SpringBoot成为构建RESTful API的首选,Nginx则作为高性能的反向代理服务器提升应用性能。本文将探讨两者如何协同工作,包括Nginx的负载均衡策略、静态资源缓存及数据压缩配置;同时讨论SpringBoot的线程池优化、缓存策略及性能监控。通过这些方法,帮助开发者显著提高系统的整体性能和可用性。
65 1
|
28天前
|
Java Spring 开发者
解锁 Spring Boot 自动化配置的黑科技:带你走进一键配置的高效开发新时代,再也不怕繁琐设置!
【8月更文挑战第31天】Spring Boot 的自动化配置机制极大简化了开发流程,使开发者能专注业务逻辑。通过 `@SpringBootApplication` 注解组合,特别是 `@EnableAutoConfiguration`,Spring Boot 可自动激活所需配置。例如,添加 JPA 依赖后,只需在 `application.properties` 配置数据库信息,即可自动完成 JPA 和数据源设置。这一机制基于多种条件注解(如 `@ConditionalOnClass`)实现智能配置。深入理解该机制有助于提升开发效率并更好地解决问题。
45 0