前言
在spring boot 源码解析2-SpringApplication初始化 中我们分析了SpringApplication的初始化.接下来我们继续分析SpringApplication的run⽅法。
解析
1. SpringApplication#run⽅法的代码如下:
public ConfigurableApplicationContext run(String... args) {
//计时工具
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
// 创建⼀个DefaultApplicationArguments对象,它持有着args参数,就是main函数传进来的参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
Banner printedBanner = this.printBanner(environment);
// 创建SpringBoot上下⽂
context = this.createApplicationContext();
new FailureAnalyzers(context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
listeners.finished(context, (Throwable)null);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
throw new IllegalStateException(var9);
}
}
该⽅法做了13件事:
1. 初始化StopWatch,调⽤其start⽅法开始计时.
2. 调⽤configureHeadlessProperty设置系统属性java.awt.headless,这⾥设置为true,表示运⾏在服务器端,在没有显示器和⿏标键盘的模式下⼯作,模拟输⼊输出设备功能
3. 调⽤SpringApplicationRunListeners#starting
4. 创建⼀个DefaultApplicationArguments对象,它持有着args参数,就是main函数传进来的参数.调⽤prepareEnvironment⽅法.
5. 打印banner
6. 创建SpringBoot上下⽂
7. 初始化FailureAnalyzers
8. 调⽤prepareContext
9. 调⽤AbstractApplicationContext#refresh⽅法,并注册钩⼦
10. 在容器完成刷新后,依次调⽤注册的Runners
11. 调⽤SpringApplicationRunListeners#finished
12. 停⽌计时
13. 初始化过程中出现异常时调⽤handleRunFailure进⾏处理,然后抛出IllegalStateException异常。
2. run⽅法中第1步.代码如下:
StopWatch stopWatch = new StopWatch();
stopWatch.start();
在StopWatch初始化时,设置id为"".代码如下:
public StopWatch() {
this("");
}
public StopWatch(String id) {
this.id = id;
}
start⽅法代码如下:
public void start() throws IllegalStateException {
this.start("");
}
public void start(String taskName) throws IllegalStateException {
if (this.running) {
throw new IllegalStateException("Can't start StopWatch: it's already running");
} else {
this.running = true;
this.currentTaskName = taskName;
this.startTimeMillis = System.currentTimeMillis();
}
}
在start⽅法中,⾸先判断当前状态是否为running.如果是的话,抛出异常.如果不是的话,将running设置为true.currentTaskName设置为"",startTimeMillis为当前时间。
在run⽅法中的第12步中,调⽤了StopWatch#stop⽅法.停⽌计时.代码如下:
public void stop() throws IllegalStateException {
if (!this.running) {
throw new IllegalStateException("Can't stop StopWatch: it's not running");
} else {
long lastTime = System.currentTimeMillis() - this.startTimeMillis;
this.totalTimeMillis += lastTime;
this.lastTaskInfo = new StopWatch.TaskInfo(this.currentTaskName, lastTime);
if (this.keepTaskList) {
this.taskList.add(this.lastTaskInfo);
}
++this.taskCount;
this.running = false;
this.currentTaskName = null;
}
}
3. run⽅法第2步--> 调⽤configureHeadlessProperty⽅法.设置系统属性java.awt.headless,这⾥设置为true,表示运⾏在服务器端,在没有显示器和⿏标键盘的模式下⼯作,模拟输⼊输出设备功能.该⽅法如下:
private void configureHeadlessProperty() {
System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
}
4. run⽅法第3步,代码如下:
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
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加载SpringApplicationRunListener.然后初始化SpringApplicationRunListeners。
对应当前场景来说,org.springframework.boot.SpringApplicationRunListener只有⼀个(配置在META-INF/spring.factories中).如下:
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
在初始化EventPublishingRunListener时,会将SpringApplication中的Listeners添加到EventPublishingRunListener中的initialMulticaster.代码如下:
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
也就是在META-INF/spring.factories中配置的org.springframework.context.ApplicationListener.关于这点,我们在上节课中讲过了。
那么在什么时候调用 EventPublishingRunListener(SpringApplication application, String[] args),这个构造方法呢?
在调用createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names)方法中调用:
T instance = BeanUtils.instantiateClass(constructor, args);
在进入Listeners之前先介绍下对应的类和作用:
ApplicationListener:事件监听者,观察者;
ApplicationEvent:Spring 事件,记录事件源、时间和数据;
ApplicationEventPublisher:发布事件;参考文章:原理洞察|Spring 事件通知机制解析
然后调⽤SpringApplicationRunListeners#starting⽅法.代码如下:
public void starting() {
Iterator var1 = this.listeners.iterator();
while(var1.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
listener.starting();
}
}
由于只有⼀个,因此会调⽤EventPublishingRunListener的starting⽅法.代码如下:
public void starting() {
this.initialMulticaster
.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}
接着调⽤SimpleApplicationEventMulticaster#multicastEvent.代码如下:
public void multicastEvent(ApplicationEvent event) {
this.multicastEvent(event, this.resolveDefaultEventType(event));
}
resolveDefaultEventType⽅法如下:
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
调⽤:
public static ResolvableType forInstance(Object instance) {
Assert.notNull(instance, "Instance must not be null");
if (instance instanceof ResolvableTypeProvider) {
ResolvableType type = ((ResolvableTypeProvider)instance).getResolvableType();
if (type != null) {
return type;
}
}
return forClass(instance.getClass());
}
由于当前传⼊的ApplicationStartedEvent不是ResolvableTypeProvider的实例,因此最终会调⽤ResolvableType#forClass.代码如下:
public static ResolvableType forClass(Class<?> clazz) {
return new ResolvableType(clazz);
}
直接初始化了ResolvableType.其构造器如下:
private ResolvableType(Class<?> clazz) {
this.resolved = clazz != null ? clazz : Object.class;
this.type = this.resolved;
this.typeProvider = null;
this.variableResolver = null;
this.componentType = null;
this.hash = null;
}
实现回到SimpleApplicationEventMulticaster#multicastEvent中,此时会调用:
ublic void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
Iterator var4 = this.getApplicationListeners(event, type).iterator();
while(var4.hasNext()) {
final ApplicationListener<?> listener = (ApplicationListener)var4.next();
Executor executor = this.getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
public void run() {
SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
}
});
} else {
this.invokeListener(listener, event);
}
}
}
该⽅法调⽤getApplicationListeners获得ApplicationListener.然后调⽤SimpleApplicationEventMulticaster#invokeListener⽅法。
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))) {
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);
}
}
该⽅法⾸先构建ListenerCacheKey,然后查询缓存中是否有的话,直接返回.否则调⽤retrieveApplicationListeners⽅法.如果
this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType,
this.beanClassLoader))) 为真的话,则调⽤retrieveApplicationListeners⽅法时会进⾏加锁.并将⽅法的返回值加⼊缓存.⼀般都会放⼊缓存的。
retrieveApplicationListeners⽅法,代码如下:
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, Class<?> sourceType, AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
LinkedList<ApplicationListener<?>> allListeners = new LinkedList();
LinkedHashSet listeners;
LinkedHashSet listenerBeans;
synchronized(this.retrievalMutex) {
listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
}
Iterator var7 = listeners.iterator();
while(var7.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var7.next();
if (this.supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
if (!listenerBeans.isEmpty()) {
BeanFactory beanFactory = this.getBeanFactory();
Iterator var15 = listenerBeans.iterator();
while(var15.hasNext()) {
String listenerBeanName = (String)var15.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) {
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
return allListeners;
}
处理逻辑如下:
1. 初始化allListeners, listeners,listenerBeans,对于当前场景来说. listeners 中的元素如下:
org.springframework.boot.context.config.ConfigFileApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.logging.LoggingApplicationListener,
org.springframework.boot.logging.ClasspathLoggingApplicationListener,
org.springframework.boot.autoconfigure.BackgroundPreinitializer,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
listenerBeans中的元素为空.
2. 遍历listeners, listenerBeans 如果监听器是否⽀持指定的事件则加⼊到allListeners.
3. 排序
疑问: listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
标红处变量是什么时候设置进去的?
对于当前场景ApplicationStartedEvent⽀持的listeners如下:
疑问: listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
标红处变量是什么时候设置进去的?
SimpleApplicationEventMulticaster#invokeListener⽅法如下:
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 {
this.doInvokeListener(listener, event);
}
}
该⽅法主要调⽤doInvokeListener,当ErrorHandler不为null时,当调⽤doInvokeListener出现异常时,会交由ErrorHandler进⾏处理.对于当前, ErrorHandler为null。
那么ErrorHandler什么时候进⾏设置呢?
未完待续。。。
doInvokeListener代码如下:
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
} catch (ClassCastException var6) {
String msg = var6.getMessage();
if (msg != null && !msg.startsWith(event.getClass().getName())) {
throw var6;
}
Log logger = LogFactory.getLog(this.getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, var6);
}
}
}
对于LoggingApplicationListener,会调⽤LoggingApplicationListener#onApplicationEvent⽅法.代码如下:
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
else if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
else if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
}
else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event)
.getApplicationContext().getParent() == null) {
onContextClosedEvent();
}
else if (event instanceof ApplicationFailedEvent) {
onApplicationFailedEvent();
}
}
接下来,LoggingApplicationListener#onApplicationStartingEvent⽅法.代码如下:
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
this.loggingSystem = LoggingSystem
.get(event.getSpringApplication().getClassLoader());
this.loggingSystem.beforeInitialize();
}
对于当前场景来说,loggingSystem为LogbackLoggingSystem.
对于BackgroundPreinitializer,DelegatingApplicationListener来说,没有做任何事。
对于LiquibaseServiceLocatorApplicationListener,代码如下:
public void onApplicationEvent(ApplicationStartingEvent event) {
if (ClassUtils.isPresent("liquibase.servicelocator.ServiceLocator", null)) {
new LiquibasePresent().replaceServiceLocator();
}
}
对于场景来说,在项⽬的类路径下,不存在liquibase.servicelocator.ServiceLocator.
本⽂就到这⾥.剩下的后续分析。