三、Springboot源码解析:SpringApplication#run(1)
创建完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 {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
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);
}
}
一步一步看吧。
一、StopWatch
这是一个秒表,用于记录程序的耗时时间,源码非常简单,一个StopWatch代表一组任务(taskList),其中有一个内部类TaskInfo代表一组任务中的某一个任务,内部类中记录了该任务的耗时时间和任务名称,用法如下:
二、获取SpringApplicationRunListeners
那么问题又来了,什么是SpringApplicationRunListeners?如何获取的?该类的注释写的非常好:Listener for the SpringApplication run method. SpringApplicationRunListeners are loaded via the SpringFactoriesLoader and should declare a public constructor that accepts a SpringApplication instance and a String[] of arguments. A new SpringApplicationRunListener instance will be created for each run.
意思就是该类是SpringApplication类中run方法的监听器,SpringApplicationRunListeners和ApplicationContextInitializer、ApplicationListener一样是通过SpringFactoriesLoader在spring.factories中获取的。debug了一下源代码,发现只有spring-boot-1.5.8.RELEASE.jar的spring.factories有org.springframework.boot.SpringApplicationRunListener对应的值:org.springframework.boot.context.event.EventPublishingRunListener,而SpringApplicationRunListeners表示的是SpringApplicationRunListener的集合,该集合的长度为1。
接下来会执行listeners.starting()
这段代码:
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
接着调用SpringApplicationRunListener的starting方法,按照上面我们说的,此处SpringApplicationRunListener对应的实现类为org.springframework.boot.context.event.EventPublishingRunListener,那就来看看它的starting方法是什么样的:
public void starting() {
this.initialMulticaster
.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}
从代码的命名来看,像是一个组播器initialMulticaster发布了一个ApplicationStartedEvent事件,在真正发布事件之前,会先将事件解析为ResolvableType,流程图如下:
从代码来看,就是根据ApplicationStartedEvent构造出来一个ResolvableType,什么是ResolvableType呢:
其实对于它的定位就是一个反射的工具类,可以让我们更方便地获取类的信息,解析完这个事件之后,就要真正发布事件了:
我们看到,在真正发布事件之前,会先调用图5中的方法,获取与该事件匹配的监听器,代码如下:
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);
private Object retrievalMutex = this.defaultRetriever;
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
private Object retrievalMutex = this.defaultRetriever;
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
//获取事件源
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
//由下面代码的命名可以大致猜测出,这一部分的代码想使用缓存,而下面的一行代码就是创建一个缓存键,ListenerCacheKey类是本类的一个内部类
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Quick check for existing entry on ConcurrentHashMap...
//ListenerRetriever是该类中的一个变量,数据结构为ConcurrentHashMap
//获取上一个cacheKey对应的ListenerRetriever,ListenerRetriever是该类的一个内部类,retrieve的意思是检索,
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
//此处retriever的值为null,所以if方法体的代码不会被执行
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
//retrievalMutex是该类的一个变量,它的值为ListenerRetriever的一个实例对象,它有一个属性Set<ApplicationListener<?>> applicationListeners的值为SpringApplication对象中存储的所有ApplicationListener,一共10个,该ListenerRetriever对象该属性的初始化是发生在实例化EventPublishingRunListener对象是赋值的。
synchronized (this.retrievalMutex) {
//retriever是该类的一个变量,值为一个空的ConcurrentHashMap,此处get的结果为null
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
//新建一个ListenerRetriever
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);
}
}
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) {
//把上面我们提到的10个监听器赋值给listeners
listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
//listenerBeans初始化,集合内没有元素,因为applicationListenerBeans的长度为0
listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
}
for (ApplicationListener<?> listener : listeners) {
//判断是否是符合该listener的时间
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
//添加符合条件的listener
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
if (!listenerBeans.isEmpty()) {
//获取BeanFactory
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;
}
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
对于上面代码,这里做一个简单总结,在初始化SpringApplication对象的时候,我们初始化了一个监听器对象列表,这里通过getApplicationListeners(event, type)筛选出监听应用启动事件的监听器,一共有四个:
然后就是发布事件了:
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);
}
}
}
接下来分别执行这四个监听器的onApplicationEvent方法,它们分别做了什么事呢?
1、LoggingApplicationListener
private LoggingSystem loggingSystem;
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
this.loggingSystem = LoggingSystem
.get(event.getSpringApplication().getClassLoader());
this.loggingSystem.beforeInitialize();
}
从代码来看,应该是初始化日志系统,因为这里不涉及比较核心的东西,就一笔带过。
2、BackgroundPreinitializer
@Override
public void onApplicationEvent(SpringApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
if (preinitializationStarted.compareAndSet(false, true)) {
performPreinitialization();
}
}
if ((event instanceof ApplicationReadyEvent
|| event instanceof ApplicationFailedEvent)
&& preinitializationStarted.get()) {
try {
preinitializationComplete.await();
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
debug了一下发现,上面的方法体中if的条件均不满足,没有执行任何实质性的代码。
3、DelegatingApplicationListener
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
if (delegates.isEmpty()) {
return;
}
this.multicaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<ApplicationEvent> listener : delegates) {
this.multicaster.addApplicationListener(listener);
}
}
if (this.multicaster != null) {
this.multicaster.multicastEvent(event);
}
}
和上一步一样,什么都没执行。
4、LiquibaseServiceLocatorApplicationListener
public void onApplicationEvent(ApplicationStartingEvent event) {
if (ClassUtils.isPresent("liquibase.servicelocator.ServiceLocator", null)) {
new LiquibasePresent().replaceServiceLocator();
}
}
也没做什么实质的东西,这里主要就是看下类路径有没有liquibase.servicelocator.ServiceLocator这个类,如果有就替换一下,猜想可能是为了修复什么漏洞而添加的一个监听器。
三、总结
本篇主要介绍了如下几个要点:
- 启动StopWatch
- 从spring.factories中获取SpringApplicationRunListeners的实例,该监听器可以理解为整个run方法的监听器,调用它的starting方法,发布一个ApplicationStartedEvent事件
- 从SpringApplication中所有的监听器中筛选出监听改事件的监听器,一共筛选出了四个
- 筛选出的四个监听器分别响应该事件,只有LoggingApplicationListener做了一些实质性的工作,那就是日志系统的初始化。
四、the next…
解析以下三行代码:
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args); - ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments); - Banner printedBanner = printBanner(environment);
上一篇: opencv打卡70: 色彩追踪(Color Tracking)
下一篇: 色彩空间的个人理解
推荐阅读
-
一个模仿oso的php论坛程序源码(之三)第1/2页
-
springboot源码怎么看(springboot源码深度解析)
-
Springboot源码 TargetSource解析
-
Springboot源码 AbstractAdvisorAutoProxyCreator解析
-
Springboot源码分析之代理三板斧
-
Spring MVC源码(三) ----- @RequestBody和@ResponseBody原理解析
-
SpringBoot 源码解析 (七)----- Spring Boot的核心能力 - SpringBoot如何实现SpringMvc的?
-
SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)
-
springboot源码怎么看(springboot源码深度解析)
-
Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析