Springboot源码跟读2--SpringApplicationRunListener的加载及starting

上一篇我们讲了SpringApplication的创建,这1篇开始讲SpringApplication的run方法:

胖子不是一口吃出来的,我们一步步来,先看部分代码:

public ConfigurableApplicationContext run(String... args) {
	// 创建时钟(主要用于记录运行时间等信息)
	StopWatch stopWatch = new StopWatch();
	// 开启时钟
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
	this.configureHeadlessProperty();
	// 获取ClassPath下的SpringApplicationRunListener实现类集合
	SpringApplicationRunListeners listeners = this.getRunListeners(args);
	// 遍历SpringApplicationRunListener实现类集合,逐个执行starting()方法
	listeners.starting();
    ...
}

解析getRunListeners方法之前,先看看SpringApplicationRunListener是个啥东东。

public interface SpringApplicationRunListener {
    void starting();

    void environmentPrepared(ConfigurableEnvironment environment);

    void contextPrepared(ConfigurableApplicationContext context);

    void contextLoaded(ConfigurableApplicationContext context);

    void started(ConfigurableApplicationContext context);

    void running(ConfigurableApplicationContext context);

    void failed(ConfigurableApplicationContext context, Throwable exception);
}

很简单,就是个接口,定义了7个方法,分别对应了SpringApplication启动的各个阶段。

当SpringApplication运行到某个阶段时,则回调各接口继承类实例该阶段对应的方法。

接着看getRunListeners方法:

private SpringApplicationRunListeners getRunListeners(String[] args) {
	Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
	return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

又看到了熟悉的getSpringFactoriesInstances方法,其目的是扫描ClassPath下所有的"META-INF/spring.factories",拿到SpringApplicationRunListener的各继承类的Class Name,然后基于反射创建各继承类的实例返回。

接着看listeners.starting():

public void starting() {
	Iterator var1 = this.listeners.iterator();

	while(var1.hasNext()) {
		SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
		listener.starting();
	}

}

就是个遍历listeners,然后调用每个SpringApplicationRunListener元素的starting()方法。

到此,即完成了SpringApplicationRunListener的加载及starting。

哈哈,是不是很简单,我们实践一波。

建一个空的Springboot Web项目,设置断点,Debug一下:

在这里插入图片描述
在这里插入图片描述
可以看到,仅有1个SpringApplicationRunListener继承类被加载,即EventPublishingRunListener。

首先,看下它的构造函数:

public EventPublishingRunListener(SpringApplication application, String[] args) {
	this.application = application;
	this.args = args;
	this.initialMulticaster = new SimpleApplicationEventMulticaster();
	Iterator var3 = application.getListeners().iterator();

	while(var3.hasNext()) {
		ApplicationListener<?> listener = (ApplicationListener)var3.next();
		this.initialMulticaster.addApplicationListener(listener);
	}

}

主要将SpringApplication创建时初始化的ApplicationListener集合赋给EventPublishingRunListener的initialMulticaster字段。

initialMulticaster.addApplicationListener方法,可以看到ApplicationListener最终被add进了ApplicationEventMulticaster的defaultRetriever.applicationListeners。

public void addApplicationListener(ApplicationListener<?> listener) {
	Object var2 = this.retrievalMutex;
	synchronized(this.retrievalMutex) {
		Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
		if (singletonTarget instanceof ApplicationListener) {
			this.defaultRetriever.applicationListeners.remove(singletonTarget);
		}

		this.defaultRetriever.applicationListeners.add(listener);
		this.retrieverCache.clear();
	}
}

applicationListeners是defaultRetriever中ApplicationListener的Set。

private class ListenerRetriever {
	public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet();
	public final Set<String> applicationListenerBeans = new LinkedHashSet();
	private final boolean preFiltered;
	...
}

Debug一下:

在这里插入图片描述

所以,EventPublishingRunListener创建后,其持有了SpringApplication创建时初始化的ApplicationListener继承类实例集合。

接着看EventPublishingRunListener的starting()方法实现:

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

首先,基于传入的SpringApplication实例和args,构建ApplicationStartingEvent传给initialMulticaster的multicastEvent方法。

public void multicastEvent(ApplicationEvent event) {
	this.multicastEvent(event, this.resolveDefaultEventType(event));
}

public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
	ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
	Iterator var4 = this.getApplicationListeners(event, type).iterator();

	while(var4.hasNext()) {
		ApplicationListener<?> listener = (ApplicationListener)var4.next();
		Executor executor = this.getTaskExecutor();
		if (executor != null) {
			executor.execute(() -> {
				this.invokeListener(listener, event);
			});
		} else {
			this.invokeListener(listener, event);
		}
	}

}

初步看就是根据event及其eventType调用getApplicationListeners(event, type)方法完成ApplicationListener的筛选。

遍历筛选后的ApplicationListener,根据event调用具体的事件方法,完成事件的发布。

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
	ErrorHandler errorHandler = this.getErrorHandler();
	if (errorHandler != null) {
		try {
			this.doInvokeListener(listener, event);
		} catch (Throwable var5) {
			errorHandler.handleError(var5);
		}
	} else {
		// 实际调用doInvokeListener
		this.doInvokeListener(listener, event);
	}
}

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
	try {
		// 传入事件,调用ApplicationListener的onApplicationEvent方法,完成事件发布
		listener.onApplicationEvent(event);
	} catch (ClassCastException var6) {
		String msg = var6.getMessage();
		if (msg != null && !this.matchesClassCastMessage(msg, event.getClass().getName())) {
			throw var6;
		}

		Log logger = LogFactory.getLog(this.getClass());
		if (logger.isDebugEnabled()) {
			logger.debug("Non-matching event type for listener: " + listener, var6);
		}
	}

}

先看getApplicationListeners方法:

protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
	Object source = event.getSource();
	Class<?> sourceType = source != null ? source.getClass() : null;
	AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
	AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
	if (retriever != null) {
		return retriever.getApplicationListeners();
	} else if (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) {
		Object var7 = this.retrievalMutex;
		synchronized(this.retrievalMutex) {
			retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
			if (retriever != null) {
				return retriever.getApplicationListeners();
			} else {
				retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true);
				Collection<ApplicationListener<?>> listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever);
				this.retrieverCache.put(cacheKey, retriever);
				return listeners;
			}
		}
	} else {
		return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null);
	}
}

首先根据eventType, sourceType构建cacheKey,然后根据cacheKey尝试从缓存中取出retriever,若retriever不为null,则直接返回retriever.getApplicationListeners(),否则通过retrieveApplicationListeners返回listeners,并更新缓存。

继续看一下retrieveApplicationListeners方法:

private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
	LinkedList<ApplicationListener<?>> allListeners = new LinkedList();
	Object var7 = this.retrievalMutex;
	LinkedHashSet listeners;
	LinkedHashSet listenerBeans;
	synchronized(this.retrievalMutex) {
		// 拿到EventPublishingRunListener持有的ApplicationListener实例集合
		// 也是SpringApplication创建时初始化的ApplicationListener实例集合
		listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
		listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
	}

	Iterator var14 = listeners.iterator();

	while(var14.hasNext()) {
		ApplicationListener<?> listener = (ApplicationListener)var14.next();
		// 调用supportsEvent为True
		// 则将该ApplicationListener添加进retriever的applicationListeners中
		if (this.supportsEvent(listener, eventType, sourceType)) {
			if (retriever != null) {
				retriever.applicationListeners.add(listener);
			}

			allListeners.add(listener);
		}
	}
	
	// 如果listenerBeans不为空,则通过beanFactory的getBean方法获取前面allListeners不包含且supportsEvent为True的ApplicationListener
	// 将其添加进retriever的applicationListeners中
	if (!listenerBeans.isEmpty()) {
		BeanFactory beanFactory = this.getBeanFactory();
		Iterator var16 = listenerBeans.iterator();

		while(var16.hasNext()) {
			String listenerBeanName = (String)var16.next();

			try {
				Class<?> listenerType = beanFactory.getType(listenerBeanName);
				if (listenerType == null || this.supportsEvent(listenerType, eventType)) {
					ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class);
					if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
						if (retriever != null) {
							retriever.applicationListenerBeans.add(listenerBeanName);
						}

						allListeners.add(listener);
					}
				}
			} catch (NoSuchBeanDefinitionException var13) {
				;
			}
		}
	}
	// 根据@Value注解排序
	AnnotationAwareOrderComparator.sort(allListeners);
	return allListeners;
}

关键在于supportsEvent方法:

protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
	GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener);
	return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
}

先将传入的ApplicationListener转成GenericApplicationListener,然后依次调用supportsEventType和supportsSourceType方法,若均返回True,则该方法返回True。

至此,SpringApplicationRunListener的加载及starting源码跟读完毕。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值