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


相关文章
|
20天前
|
Java 调度 Spring
SpringBoot实现多线程定时任务动态定时任务配置文件配置定时任务
SpringBoot实现多线程定时任务动态定时任务配置文件配置定时任务
40 0
|
1月前
|
安全 Java 数据安全/隐私保护
SpringBoot实现二维码扫码登录的原理与详细步骤
SpringBoot实现二维码扫码登录的原理与详细步骤
81 1
|
1月前
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
46 0
|
2月前
|
缓存 Java Maven
Spring Boot自动配置原理
Spring Boot自动配置原理
48 0
|
1月前
|
SQL Java 数据库连接
springboot中配置mybatis别名该怎么写?
springboot中配置mybatis别名该怎么写?
22 0
|
2月前
|
Java 程序员 API
Springboot-swagger配置(idea社区版2023.1.4+apache-maven-3.9.3-bin)
Springboot-swagger配置(idea社区版2023.1.4+apache-maven-3.9.3-bin)
58 1
|
1月前
|
前端开发 搜索推荐 Java
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
|
9天前
|
Java Shell 测试技术
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
17 0
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
|
12天前
|
Java 容器 Spring
Springboot自动配置原理
Springboot自动配置原理
|
13天前
|
Java 容器
SpringBoot使用配置注解开启自动配置功能&整合spring-boot-configuration-processor
SpringBoot使用配置注解开启自动配置功能&整合spring-boot-configuration-processor
12 0