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 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
4月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
841 0
|
4月前
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 &gt; Java系统属性 &gt; application.properties &gt; application.yml &gt; application.yaml。
864 0
|
1月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
237 3
|
1月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
315 2
|
2月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
481 5
|
2月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
164 0
探索Spring Boot的@Conditional注解的上下文配置
|
8月前
|
缓存 Java API
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
本文介绍了在Spring Boot中配置Swagger2的方法。通过创建一个配置类,添加`@Configuration`和`@EnableSwagger2`注解,使用Docket对象定义API文档的详细信息,包括标题、描述、版本和包路径等。配置完成后,访问`localhost:8080/swagger-ui.html`即可查看接口文档。文中还提示了可能因浏览器缓存导致的问题及解决方法。
953 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
|
3月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
916 10
|
4月前
|
前端开发 Java 数据库连接
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)