SpringBoot内部事件监听器匹配原理和自定义匹配规则

目的

  • 理解SpringBoot事件监听机制如何实现?
  • 如何实现自己需要的事件、监听器匹配规则?

 

1.SpringBoot事件监听器原理(源码角度)

SpringBoot内部事件中已经讲解了SpringBoot内部事件、事件发布、事件监听的流程以及相关的核心接口和类。这里讲解事件监听是如何实现的?

  • 流程总述:创建事件 --> 广播器发布事件 --> 根据事件类型从context的listeners集合中匹配到对应的监听器 --> 回调监听器的onApplication()方法。
  • 如何根据事件匹配监听器?     不同的监听器中预置可能对应的事件类型,然后通过class.isAssignableFrom()判断传入的事件在监听器内预置事件中是否存在(妙!)。

1.1 SpringBoot启动流程事件监听举例

在SpringBoot启动run()过程中,首先启动的事件是ApplicationStartingEvent。对应run()方法中的listeners.starting(),而实际执行则在EventPublishingRunListener对象中,存在starting()方法。

starting()方法中,首先创建了ApplicationStartingEvent事件,然后通过广播器.multicastEvent()发布了该事件。

@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(
				new ApplicationStartingEvent(this.application, this.args));
	}

1.2 事件发布监听关键点

(1)根据传入的事件从所有的listener中匹配对应的监听器。

(2)回调监听器的onApplication()方法。

(1)根据事件匹配监听器

下面代码块中的getApplicationListeners方法是关键,而getApplicationListeners最终执行到retrieveApplicationListeners方法,最后根据supportsEvent()方法中的class.isAssignableFrom()  java本地方法方法判断监听器是否匹配传入的事件。

class.isAssignableFrom()方法:

class1.isAssignableFrom(class2) 判定此 class1 对象所表示的类或接口与指定的 class2 参数所表示的类或接口是否相同,或是否是其超类或超接口。

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    //getApplicationListeners是关键
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			Executor executor = getTaskExecutor();
    //回调监听器的方法
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}


protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {
    //...
    //真正根据事件类型判断监听器的方法
	Collection<ApplicationListener<?>> listeners = 
retrieveApplicationListeners(eventType, sourceType, retriever);
				    //...
	}
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
			ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {

    //...
    //此处的判断条件是关键部分,supportEvent方法
			if (supportsEvent(listener, eventType, sourceType)) {
    //...
	}
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
		GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
				(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
		return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
	}


@Override
	public boolean supportsEventType(ResolvableType resolvableType) {
		return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
	}
@Override
	public boolean supportsSourceType(Class<?> sourceType) {
		return isAssignableFrom(sourceType, SOURCE_TYPES);
	}


//日志LoggingApplicationListener事件当中,预置了EVENT_TYPES事件类型
EVENT_TYPES = { ApplicationStartingEvent.class,
			ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class,
			ContextClosedEvent.class, ApplicationFailedEvent.class };
//根据传入的事件,匹配是否在事件集合中
isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);

(2)回调监听器的方法

@SuppressWarnings({"unchecked", "rawtypes"})
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
    //关键点在这里。回调了监听器listener.onApplicationEvent()方法。至此,事件从发布到执行结束
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isDebugEnabled()) {
					logger.debug("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

 

2.如何实现自定义事件监听器匹配规则?

自定义监听器匹配规则,暂时还未深入理解。下面这篇文章推荐阅读:https://juejin.cn/post/6955783021224001567

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值