上一篇我们讲了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.jpg 2.jpg可以看到,仅有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一下:
3.jpg所以,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源码跟读完毕。
网友评论