SpringBoot监听器

本文深入解析Spring框架中的事件监听机制,包括多播器初始化、监听器注册及事件发布过程。探讨如何实现事件的异步发布,并提供代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说到事件监听,想到的肯定是观察者模式。但是这儿主要说下spring中的监听是怎么样的流程。

这就不得不说到spring容器的refresh方法,容器启动过程中,listener相关的主要是这个三个方法:initApplicationEventMulticaster方法初始化事件多播器,后续的事件发布都是由多播器来发布的;registerListeners注册监听器到前面初始化好的多播器上面去;

finishRefresh容器启动完成最后刷新,发布ContextRefreshedEvent事件。
在这里插入图片描述
1.初始化多播器:获取bean工厂对象ConfigurableListableBeanFactory,判断容器中是否有applicationEventMulticaster多播器,如果没有则创建一个一个简单事件多播器SimpleApplicationEventMulticaster并注册到容器中,后续使用
在这里插入图片描述
在这里插入图片描述
2.注册监听器到多播器上并发布早期事件:首先获取容器中已有的监听器(成品对象,从第一张图中可以看到我们自己的组件对象在registerListeners方法调用的时候 还没有初始化,是在下面的finishBeanFactoryInitialization方法中才进行初始化的),注册到多播器;然后获取bean定义中的监听器,也就是我们自己定义的监听器;同样也注册到多播器上去;最后如果有早期事件就去发布早期事件(multicastEvent方法),这些事件只能由已经实例化的监听器监听,我们自己的监听器初始化是在finishBeanFactoryInitialization方法中。
在这里插入图片描述
发布事件:multicastEvent方法----->invokeListener方法---->doInvokeListener方法调用监听器的onApplicationEvent
在这里插入图片描述
可以看到这里支持异步发送,但是从上面我们初始化简单多播器的时候,executer对象并没有赋值,因此始终是同步发布。如果我们想实现异步发布事件,那么就要让上面初始化多播器的逻辑走进第一个分支。我们可以在容器中自己继承SimpleApplicationEventMulticaster,并初始化一个线程池,然后将其注册到容器中,bean的名字必须使用“applicationEventMulticaster”,因为此时容器还没有创建真正的对象,只有这个名字的bean定义才会马上去创建对象。这样就可以实现异步发布事件了。

3.执行finishRefresh方法发布ContextRefreshedEvent事件,标志的容器已经启动完成。
在这里插入图片描述
自定义监听器

监听器

package com.example.demo.listener;

import com.example.demo.event.MyApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 监听器
 *
 * @author: zhangqi
 * @create: 2022/3/27 11:07
 */
@Component
public class MyListener implements ApplicationListener<MyApplicationEvent> {

    @Override
    public void onApplicationEvent(MyApplicationEvent event) {
        System.out.println("收到事件:" + event.getCustomParam());
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

事件

package com.example.demo.event;

import lombok.Getter;
import org.springframework.context.ApplicationEvent;

/**
 * @author: zhangqi
 * @create: 2022/3/27 11:09
 */
@Getter
public class MyApplicationEvent extends ApplicationEvent {
    private static final long serialVersionUID = 3516933308167019932L;
    /**
     * 自定义的参数
     */
    private String customParam;

    public MyApplicationEvent(Object source, String customParam) {
        super(source);
        this.customParam = customParam;
    }
}

测试

package com.example.demo.test;

import com.example.demo.event.MyApplicationEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author: zhangqi
 * @create: 2022/3/27 11:14
 */
@RestController
public class TestController {

    @Resource
    private ApplicationContext applicationContext;


    @GetMapping("test")
    public String test() {
        applicationContext.publishEvent(new MyApplicationEvent(this, "自定义的参数"));
        return "成功";
    }

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值