前言
在spring boot 源码解析2-SpringApplication初始化 中我们分析了SpringApplication的初始化.接下来我们继续分析SpringApplication的run方法.
解析
SpringApplication#run方法的代码如下:
public ConfigurableApplicationContext run(String... args) { // 计时工具 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { // 创建一个DefaultApplicationArguments对象,它持有着args参数,就是main函数传进来的参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); // 创建SpringBoot上下文 context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
该方法做了13件事:
初始化StopWatch,调用其start方法开始计时.
调用configureHeadlessProperty设置系统属性java.awt.headless,这里设置为true,表示运行在服务器端,在没有显示器和鼠标键盘的模式下工作,模拟输入输出设备功能
调用SpringApplicationRunListeners#starting
创建一个DefaultApplicationArguments对象,它持有着args参数,就是main函数传进来的参数.调用prepareEnvironment方法.
打印banner
创建SpringBoot上下文
初始化FailureAnalyzers
调用prepareContext
调用AbstractApplicationContext#refresh方法,并注册钩子
在容器完成刷新后,依次调用注册的Runners
调用SpringApplicationRunListeners#finished
停止计时
初始化过程中出现异常时调用handleRunFailure进行处理,然后抛出IllegalStateException异常.
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 { start(""); } public void start(String taskName) throws IllegalStateException { if (this.running) { throw new IllegalStateException("Can't start StopWatch: it's already running"); } 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"); } long lastTime = System.currentTimeMillis() - this.startTimeMillis; this.totalTimeMillis += lastTime; this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime); if (this.keepTaskList) { this.taskList.add(lastTaskInfo); } ++this.taskCount; this.running = false; this.currentTaskName = null; }
还是同样的套路.如果running为false –> 抛出异常.如果不是.则计算得出lastTime.初始化TaskInfo.将TaskInfo加入到taskList中.增加taskCount计数器.将running设为false,将currentTaskName置为null.
run方法第2步–> 调用configureHeadlessProperty方法.设置系统属性java.awt.headless,这里设置为true,表示运行在服务器端,在没有显示器和鼠标键盘的模式下工作,模拟输入输出设备功能.该方法如下:
private void configureHeadlessProperty() { System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty( SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless))); }
run方法第3步,代码如下:
SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting();
getRunListeners方法如下:
private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)); }
还是同样的味道.通过调用getSpringFactoriesInstances加载SpringApplicationRunListener.然后初始化SpringApplicationRunListeners.
对应当前场景来说,org.springframework.boot.SpringApplicationRunListener只有一个.如下:
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); } }
然后调用SpringApplicationRunListeners#starting方法.代码如下:
public void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } }
由于只有一个,因此会调用EventPublishingRunListener的starting方法.代码如下:
public void starting() { this.initialMulticaster .multicastEvent(new ApplicationStartedEvent(this.application, this.args)); }
接着调用SimpleApplicationEventMulticaster#multicastEvent.代码如下:
public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); }
调用
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { 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); // 1. 构造ListenerCacheKey ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Quick check for existing entry on ConcurrentHashMap... // 2. 如果retrieverCache中有的话,直接返回 ListenerRetriever retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { // Fully synchronized building and caching of a ListenerRetriever synchronized (this.retrievalMutex) { retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } retriever = new ListenerRetriever(true); Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } else { // No ListenerRetriever caching -> no synchronization necessary return retrieveApplicationListeners(eventType, sourceType, 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, ListenerRetriever retriever) { LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>(); Set<ApplicationListener<?>> listeners; Set<String> listenerBeans; synchronized (this.retrievalMutex) { listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans); } for (ApplicationListener<?> listener : listeners) { if (supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListeners.add(listener); } allListeners.add(listener); } } if (!listenerBeans.isEmpty()) { BeanFactory beanFactory = getBeanFactory(); for (String listenerBeanName : listenerBeans) { try { Class<?> listenerType = beanFactory.getType(listenerBeanName); if (listenerType == null || supportsEvent(listenerType, eventType)) { ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class); if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListenerBeans.add(listenerBeanName); } allListeners.add(listener); } } } catch (NoSuchBeanDefinitionException ex) { // Singleton listener instance (without backing bean definition) disappeared - // probably in the middle of the destruction phase } } } AnnotationAwareOrderComparator.sort(allListeners); return allListeners; }
处理逻辑如下:
初始化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中的元素为空.
遍历listeners, listenerBeans 如果监听器是否支持指定的事件则加入到allListeners.
- 排序
对于当前场景ApplicationStartedEvent支持的listeners如下:
org.springframework.boot.logging.LoggingApplicationListener, org.springframework.boot.autoconfigure.BackgroundPreinitializer, org.springframework.boot.context.config.DelegatingApplicationListener, org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
SimpleApplicationEventMulticaster#invokeListener方法如下:
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { doInvokeListener(listener, event); } catch (Throwable err) { errorHandler.handleError(err); } } else { 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 ex) { String msg = ex.getMessage(); if (msg == null || msg.startsWith(event.getClass().getName())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for Log logger = LogFactory.getLog(getClass()); if (logger.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } }
对于LoggingApplicationListener,会调用LoggingApplicationListener#onApplicationStartingEvent方法.代码如下:
private void onApplicationStartingEvent(ApplicationStartingEvent event) { this.loggingSystem = LoggingSystem .get(event.getSpringApplication().getClassLoader()); this.loggingSystem.beforeInitialize(); }
对于当前场景来说,loggingSystem为LogbackLoggingSystem.
对于BackgroundPreinitializer,DelegatingApplicationListener来说,没有做任何事.
对于LiquibaseServiceLocatorApplicationListener,代码如下:
@Override public void onApplicationEvent(ApplicationStartingEvent event) { if (ClassUtils.isPresent("liquibase.servicelocator.ServiceLocator", null)) { new LiquibasePresent().replaceServiceLocator(); } }
对于场景来说,在项目的类路径下,不存在liquibase.servicelocator.ServiceLocator.
本文就到这里.剩下的后续分析.