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配置监听器的步骤方式,原理和自带的事件等。


相关文章
|
27天前
|
缓存 Java API
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
本文介绍了在Spring Boot中配置Swagger2的方法。通过创建一个配置类,添加`@Configuration`和`@EnableSwagger2`注解,使用Docket对象定义API文档的详细信息,包括标题、描述、版本和包路径等。配置完成后,访问`localhost:8080/swagger-ui.html`即可查看接口文档。文中还提示了可能因浏览器缓存导致的问题及解决方法。
64 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
|
27天前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
76 0
|
27天前
|
Java 测试技术 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
26 0
|
27天前
|
SQL Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
99 0
|
17天前
|
Java Spring
SpringBoot自动配置原理
本文深入解析了SpringBoot的核心功能——自动配置,重点探讨了`org.springframework.boot.autoconfigure`及相关注解的工作机制。通过分析`@SpringBootApplication`、`@EnableAutoConfiguration`等注解,揭示了SpringBoot如何基于类路径和条件自动装配Bean
66 7
|
28天前
|
Java
SpringBoot自动装配的原理
在SpringBoot项目的启动引导类上都有一个注解@SpringBootApplication 这个注解是一个复合注解, 其中有三个注解构成 , 分别是 ● @SpringBootConfiguration : 是@Configuration的派生注解 , 标注当前类是一个SpringBoot的配置类 ● @ComponentScan : 开启组件扫描, 默认扫描的是当前启动引导了所在包以及子包 ● @EnableAutoConfiguration : 开启自动配置(自动配置核心注解) 2.在@EnableAutoConfiguration注解的内容使用@Import注解导入了一个AutoC
|
7天前
|
安全 前端开发 Java
Spring Boot 项目中触发 Circular View Path 错误的原理与解决方案
在Spring Boot开发中,**Circular View Path**错误常因视图解析与Controller路径重名引发。当视图名称(如`login`)与请求路径相同,Spring MVC无法区分,导致无限循环调用。解决方法包括:1) 明确指定视图路径,避免重名;2) 将视图文件移至子目录;3) 确保Spring Security配置与Controller路径一致。通过合理设定视图和路径,可有效避免该问题,确保系统稳定运行。
41 0
|
1月前
|
JavaScript 前端开发 Java
Idea启动SpringBoot程序报错:Veb server failed to start. Port 8082 was already in use;端口冲突的原理与解决方案
本文解决了Idea启动SpringBoot程序报错:Veb server failed to start. Port 8082 was already in use的问题,并通过介绍端口的使用原理和操作系统的端口管理机制,可以更有效地解决端口冲突问题,并确保Web服务器能够顺利启动和运行。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
2月前
|
Cloud Native Java Nacos
springcloud/springboot集成NACOS 做注册和配置中心以及nacos源码分析
通过本文,我们详细介绍了如何在 Spring Cloud 和 Spring Boot 中集成 Nacos 进行服务注册和配置管理,并对 Nacos 的源码进行了初步分析。Nacos 作为一个强大的服务注册和配置管理平台,为微服务架构提供
474 14
|
2月前
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
121 12

热门文章

最新文章