SpringBoot中的监听机制

SpringBoot中内置的监听器

内置监听器都定义在在spring.factories文件中

监听器 监听事件 说明
ClearCachesApplicationListener ContextRefreshedEvent 当触发ContextRefreshedEvent事件会清空应用的缓存
ParentContextCloserApplicationListener ParentContextAvailableEvent 触发ParentContextAvailableEvent事件会完成父容器关闭的监听器
CloudFoundryVcapEnvironmentPostProcessor ApplicationPreparedEvent 判断环境中是否存在VCAP_APPLICATION或者VCAP_SERVICES。如果有就添加Cloud Foundry的配置;没有就不执行任何操作。
FileEncodingApplicationListener ApplicationEnvironmentPreparedEvent 文件编码的监听器
AnsiOutputApplicationListener ApplicationEnvironmentPreparedEvent 根据 spring.output.ansi.enabled参数配置 AnsiOutput
ConfigFileApplicationListener ApplicationEnvironmentPreparedEventApplicationPreparedEvent 完成相关属性文件的加载,application.properties、 application.yml
DelegatingApplicationListener ApplicationEnvironmentPreparedEvent 监听到事件后转发给环境变量 context.listener.classes指定的那些事件监听器
ClasspathLoggingApplicationListener ApplicationEnvironmentPreparedEventApplicationFailedEvent 一个SmartApplicationListener,对环境就绪事件ApplicationEnvironmentPreparedEvent/应用失败事件ApplicationFailedEvent做出响应,往日志DEBUG级别输出TCCL(thread context class loader)的classpath。
LoggingApplicationListener ApplicationStartingEvent ApplicationEnvironmentPreparedEvent ApplicationPreparedEventContextClosedEventApplicationFailedEvent 配置 LoggingSystem。使用 logging.config环境变量指定的配置或者缺省配置
LiquibaseServiceLocatorApplicationListener ApplicationStartingEvent 使用一个可以和Spring Boot可执行jar包配合工作的版本替换liquibase ServiceLocator
BackgroundPreinitializer ApplicationStartingEventApplicationReadyEventApplicationFailedEvent 尽早触发一些耗时的初始化任务,使用一个后台线程

自定义监听器和监听事件

自定义监听事件

需要继承ApplicationEvent

scala 复制代码
public class MyEvent extends ApplicationEvent {
    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public MyEvent(Object source) {
        super(source);
    }
}

自定义监听器

需要实现ApplicationListener接口

csharp 复制代码
/**
 * @author 26917
 * 自定义监听器
 *  监听自定义的事件
 */
public class MyCustomerEventListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        System.out.println("MyCustomerEventListener ----》 自定义事件触发" + event);
    }
}

ApplicationListener类图

将这个自定义的监听器加入到spring.factories文件中

ini 复制代码
org.springframework.context.ApplicationListener=\
com.nyc.listener.MyCustomerEventListener

使用这个监听器

typescript 复制代码
@RestController
public class UserController {
    @Autowired
    private ApplicationContext context;
    @GetMapping("/hello")
    public String hello(){
        context.publishEvent(new MyEvent(new Object()));
        return "hello";
    }
}

监听器代码分析

类图分析

getRunListeners(args)方法

这个方法获取到事件发布器

EventPublishingRunListener 构造方法

kotlin 复制代码
public EventPublishingRunListener(SpringApplication application, String[] args) {
    this.application = application;
    this.args = args;
    // 初始化多个监听器,其实就是我们前面加载的spring.factories文件中的11个监听器
    this.initialMulticaster = new SimpleApplicationEventMulticaster();
    // application.getListeners() 获取11个监听器
    for (ApplicationListener<?> listener : application.getListeners()) {
        // 绑定初始的11个监听器
        this.initialMulticaster.addApplicationListener(listener);
    }
}

listeners.starting()方法

触发启动事件 -》发布starting事件,那么监听starting事件的监听器就会触发

typescript 复制代码
class SpringApplicationRunListeners {

	private final Log log;

	private final List<SpringApplicationRunListener> listeners;

	SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = new ArrayList<>(listeners);
	}

	void starting() {
		// 发布器 EventPublishingRunListener
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}

	void environmentPrepared(ConfigurableEnvironment environment) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.environmentPrepared(environment);
		}
	}

	void contextPrepared(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.contextPrepared(context);
		}
	}

	void contextLoaded(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.contextLoaded(context);
		}
	}

	void started(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.started(context);
		}
	}

	void running(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.running(context);
		}
	}

	void failed(ConfigurableApplicationContext context, Throwable exception) {
		for (SpringApplicationRunListener listener : this.listeners) {
			callFailedListener(listener, context, exception);
		}
	}

	private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
			Throwable exception) {
		try {
			listener.failed(context, exception);
		}
		catch (Throwable ex) {
			if (exception == null) {
				ReflectionUtils.rethrowRuntimeException(ex);
			}
			if (this.log.isDebugEnabled()) {
				this.log.error("Error handling failed", ex);
			}
			else {
				String message = ex.getMessage();
				message = (message != null) ? message : "no error message";
				this.log.warn("Error handling failed (" + message + ")");
			}
		}
	}

}

SpringApplicationRunListeners类的作用

SpringApplicationRunListener 的集合代理类,用来统一调度并触发所有 RunListener,整体监视 Spring Boot 启动过程的各个阶段。

在源码中SpringApplicationRunListener接口的默认实现就只有,EventPublishingRunListener

EventPublishingRunListener类的starting方法。

typescript 复制代码
@Override
public void starting() {
    this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}

在springboot的启动的时候会在以下几个阶段进行监听器发布,分别是启动阶段、环境配置准备阶段、容器上下文准备阶段、启动完成阶段、启动失败阶段以及运行阶段。

相关推荐
晚安code几秒前
设计模式入门:吃透 SOLID 原则与迪米特法则,再学 5 个高频模式
后端·设计模式
专业程序开发源2 小时前
django新闻推荐系统70655-计算机课程设计、毕业设计
java·javascript·spring boot·后端·python·django·课程设计
打工仔折腾 AI3 小时前
把 AI Agent 托管到家里电脑:UU远程端口映射与CLI实测记录
人工智能·后端·python·langchain·电脑·ai agent 实战
vx_Biye_Design3 小时前
springboot一站式旅游管理平台81037-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·课程设计·express·旅游
嵌入式学习菌3 小时前
ESP32 ModbusTCP 分片缓存
java·后端·spring
程序员小杰@3 小时前
Spring Boot 常用注解分类速记
java·spring boot·后端
挖掘狂人3 小时前
Git 从 0 到 1:用一个小项目走完 add / commit / reset / merge / rebase / push
git·后端·github
vx_Biye_Design3 小时前
springboot小学生英语学习APP62773-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·python·学习·课程设计
打工仔折腾 AI3 小时前
用UU远程把家里电脑变成AI Agent常驻服务器:CLI、端口映射与代理实测
运维·服务器·人工智能·后端·python·电脑·ai agent 实战
明月_清风3 小时前
AI Agent 进入系统层:现在有哪些开源项目在解决这个问题?
人工智能·后端