2.Springboot之ApplicationContext&Listener&Config

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代表用户传递的数据。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值