当前位置: 首页 > article >正文

2.Springboot之ApplicationContextListenerConfig

Springboot中监听器属于事件发布机制范畴,其中角色包含:发布者、事件、监听者。

  • 监听器Listener:SpringApplicationRunListener & ApplicationListener。用于处理发布者发布的事件。
  • 发布者:ApplicationEventPublisher & ApplicationEventMulticaster。
  • 事件:ApplicationEvent。

 监听器贯穿在Springboot框架整个生命周期内:

  1. 阶段1:容器刷新之前。
  2. 阶段2:容器刷新完毕之前的监听机制。
  3. 阶段3:容器刷新完毕之后的监听机制

1.不同阶段的监听器

public abstract class AbstractApplicationContext{
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		...
		// 阶段二
		initApplicationEventMulticaster();
		// 阶段二:主要初始化 WebServer
		onRefresh();
		// 阶段二:earlyApplicationEvents类型的事件
		registerListeners();
		// Instantiate all remaining (non-lazy-init) singletons.
		finishBeanFactoryInitialization(beanFactory);
		// 阶段三
		finishRefresh();
	}	
}

1.1.阶段1之SpringApplicationRunListener

EventPublishingRunListener作为该监听器唯一的实现类是通过SPI机制从META-INF/spring.factories文件中加载得到的。

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    // ApplicationEventMulticaster 类型的发布器
	private final SimpleApplicationEventMulticaster initialMulticaster;

	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
	}
}

该监听器贯穿在SpringBoot应用启动过程中不同的阶段,每个阶段会触发不同的ApplicationEvent。例如:ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent等。

严格意义来说当前Listener并非是真正的监听器,因为其并非处理ApplicationEvent,反而是借助发布者ApplicationEventMulticaster发布上述不同阶段的事件,从这个意义来说更适合将其归类为顶级发布者Publisher。


1.2.阶段2之earlyApplicationEvents

该阶段是为应用上下文ApplicationContext初始化ApplicationEventMulticaster类型的发布者,区别于阶段1之SpringApplicationRunListener内部的发布者ApplicationEventMulticaster。

public abstract class AbstractApplicationContext{
	// 此时该集合属性中的ApplicationListener 为 SPI机制获取的监听器
	private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
    
    private ApplicationEventMulticaster applicationEventMulticaster;

	private Set<ApplicationEvent> earlyApplicationEvents;

	protected void registerListeners() {
		// 将已知的监听器添加到ApplicationContext中的发布者 ApplicationEventMulticaster
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}
		// 从即将被IOC容器托管的众多类中获取 ApplicationListener类型的BeanNames ~ 注意此时尚未初始化ioc容器
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// 如果集合earlyApplicationEvents存在ApplicationEvent元素
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				//利用 ApplicationContext中ApplicationEventMulticaster持有的全部监听器尝试发送集合earlyEventsToProcess中全部事件
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

	public Collection<ApplicationListener<?>> getApplicationListeners() {
		return this.applicationListeners;
	}
}

从上述伪代码分析得知:该阶段的监听器完全作用于应用上下文ApplicationContext。

ApplicationContext也是ApplicationEventPublisher类型的发布者。集合earlyApplicationEvents中的元素必须ApplicationContext发布的事件,否则事件是不会被添加到earlyApplicationEvents中

在该阶段之前任何时候由发布者ApplicationContext发布的所有事件都被作为集合earlyApplicationEvents中的元素,并在此时由ApplicationContext持有的applicationEventMulticaster来触发全部的监听器处理集合earlyApplicationEvents中全部事件。


1.3.阶段3

该阶段的事件即为容器刷新完毕之后发生的事件。

public abstract class AbstractApplicationContext{
	protected void finishRefresh() {
		initLifecycleProcessor();
		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();
		// Publish the final event.
		publishEvent(new ContextRefreshedEvent(this));
		...
	}
}

其中,Lifecycle内部会触发ServletWebServerInitializedEvent类型的事件。


2.ApplicationListener

该类型的监听器获取存在两种形式:spring.factories文件 & 监听器Listener以bean形式被ioc容器管理并获取。

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	void onApplicationEvent(E event);
}

如上所示监听器处理 ApplicationEvent 的核心方法。

public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
	boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
	default boolean supportsSourceType(@Nullable Class<?> sourceType) {
		return true;
	}
}

如果使用方直接实现接口ApplicationListener,则意味着需要处理所有的ApplicationEvent,包含框架自身出发的事件以及用户自定义Publisher触发的事件。

通常自定义的监听器直接实现SmartApplicationListener or GenericApplicationListener接口,好处是可以根据ApplicationEvent类型 or source类型过滤掉非关注的事件。


2.发布者


2.1.ApplicationEventPublisher

ApplicationEventPublisherAware为例:

这种Aware类型的接口是被ApplicationContextAwareProcessor后置处理器触发回调的。

public interface ApplicationEventPublisherAware extends Aware {
	void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);
}

注意此时发布者applicationEventPublisher类型为 ApplicationContext。

public abstract class AbstractApplicationContext{

	private Set<ApplicationEvent> earlyApplicationEvents;

	public void publishEvent(Object event) {
		publishEvent(event, null);
	}

	protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
		ApplicationEvent applicationEvent;
		if (event instanceof ApplicationEvent) {
			applicationEvent = (ApplicationEvent) event;
		}else {
			...
		}
		//此时由于处于 所有bean实例化、初始化阶段,此时属性 earlyApplicationEvents 被提前置为空
		if (this.earlyApplicationEvents != null) {
			this.earlyApplicationEvents.add(applicationEvent);
		}else {
			// ApplicationEventPublisherAware 触发的事件,由关注 事件类型eventType 的监听器负责处理
			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
		}
		...
	}
}

用户自定义一个对eventType事件类型感兴趣的监听器ApplicationListener,并处理该事件。


2.2.ApplicationEventMulticaster

通过上述章节分析得知:该类型的Publisher只是适用于SpringApplicationRunListener、ApplicationContext内部。

当前发布者发布的事件涉及哪些监听器:

  1. 阶段一:META-INF/spring.factories文件中内置的ApplicationListener。
  2. 阶段二:除了阶段一,还包括用户自定义被IOC托管的监听器。

3.ApplicationEvent

public abstract class ApplicationEvent extends EventObject {
	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}
}

其中,source代表用户传递的数据。



http://www.kler.cn/news/309705.html

相关文章:

  • 【四范式】浅谈NLP发展的四个范式
  • 怀揣热爱 躬耕不惫 ——记新宁县金石镇水头学校朱文文老师
  • 雷池waf:三步轻松卸载指南
  • Redis - 集群篇 - 集群模式
  • 系统安全设计规范(Word完整版)
  • 如何用麦肯锡方法分析问题和解决问题?
  • navicate连接oracle数据库probable oracle net admin error
  • C++:内部类,匿名对象,操作符new与delete
  • uniapp 做一个查看图片的组件,图片可缩放移动
  • python中Web API 框架
  • Html css样式总结
  • 使用CUBE_MX实现STM32 DMA 功能(存储器到存储器)
  • Miracast/WifiDisplay开发相关的深入调研分析-android投屏实战开发
  • 字幕编辑用什么软件好?盘点国内外7款视频加字幕软件,简单高效!
  • [SWPU2019]Web11
  • Java文件输入输出及其常用类
  • Nginx反向代理出现502 Bad Gateway问题的解决方案
  • 如何使用 LangChain 的内置工具和工具包:深入探讨与实践指南
  • [Web安全 网络安全]-文件包含漏洞
  • 八股(8)——Spring,SpringBoot
  • 虾皮商品数据api全解析:高效获取,精准运营新利器
  • 记八月十五灵隐寺一游
  • presto/trino native 向量化 大数据计算引擎
  • MySQL之库和表操作
  • Rust 所有权 简介
  • 硬件基础知识
  • 计算机人工智能前沿进展-大语言模型方向-2024-09-13
  • [SIGGRAPH-24] CharacterGen
  • 使用c#制作一个小型桌面程序
  • 彩漩科技亮相第一届人工智能教育应用论坛,入选TOP30榜单,展示创新教育科技产品