Springboot启动流程(二)
之前我们看了Application的赋值流程,之后的run方法调用才是启动流程的重点:
run方法代码如下:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
try 之前的代码是获取和执行listeners的,同样调用了getSpringFactoriesInstances方法获取的对象,代码:
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class>[] types = new Class>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
获取了SpringApplicationRunListener的对象数组并且放入SpringApplicationRunListeners中.之后调用starting方法开启全部listener:
SpringApplicationRunListeners 类:
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
调用了EventPublishingRunListener的starting方法,我们来看下具体代码:
EventPublishingRunListener 类:
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);
}
}
@Override
public void starting() {
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
首先是调用构造方法为initialMulticaster赋值,然后把application.getListeners()获得的所有listener加到initialMulticaster中,
application的listener的获取方法在之前获取SpringApplication对象时已经获取过了.
addApplicationListener 方法:
AbstractApplicationEventMulticaster 类:
@Override
public void addApplicationListener(ApplicationListener> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
以上代码首先去除了所有实现了aop的listener对象,然后把listener放入defaultRetriever的applicationListeners中,最后清除缓存
defaultRetriever是AbstractApplicationEventMulticaster的内部类,他主要是囊括了特定的listener来有效的搜寻listeners
/**
* Helper class that encapsulates a specific set of target listeners,
* allowing for efficient retrieval of pre-filtered listeners.
*
An instance of this helper gets cached per event type and source type.
*/
为什么要去除实现了aop的对象?
上面的注释解释了原因:为了避免多次调用一个listener!
在一系列的出事话event操作后,开始真正的处理listener:
new 了一个ApplicationStartingEvent对象并把它放入initialMulticaster的multicastEvent中.
SimpleApplicationEventMulticaster 中的multicastEvent方法:
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
从上面的代码可以初步分析出他是用来调用listener的方法.
首先调用resolveDefaultEventType方法处理event,这个resolveDefaultEventType是干什么的呢?
resolveDefaultEventType:
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
他直接调用了ResolvableType.forInstance(event)方法:
ResolvableType 类:
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 ResolvableType.forClass(instance.getClass());
}
如果instance实现了ResolvableTypeProvider接口则使用ResolvableTypeProvider.getResolvableType方法获取type,否则使用forClass方法获取,
ResolvableTypeProvider.getResolvableType调用了forClassWithGenerics方法并传入通过playload获取的ResolvableType对象
具体意思就是如果实现了ResolvableTypeProvider接口则返回带属性type的ResolvableType对象否则返回不带属性的对象
获取完eventType后开始处理listeners
protected Collection
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Quick check for existing entry on ConcurrentHashMap...
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
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// No ListenerRetriever caching -> no synchronization necessary
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
调用了getApplicationListeners方法:
首先第一个问题:
Object source = event.getSource();获取的object是什么?
我们回来看starting的代码:
@Override
public void starting() {
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
他new了一个ApplicationStartingEvent对象,其构造方法调用了super();构造了一个SpringApplicationEvent对象,SpringApplicationEvent的构造方法
又调用了super构造了ApplicationEvent的抽象类,这个抽象类是继承EventObject类的,而EventObject的构造方法把传入的resouce存入对象中,所以
event.getSource();方法获取的是一开始传入的application对象,既创建对象时传入的this:SpringApplication对象!
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
接下来包装了一个缓存的key并且使用这个key获取ListenerRetriever对象,但我们是第一次调用所以要接着向下走
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))))
beanClassLoader没有被赋值所以会进入这个if中处理:
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
首先在判断下缓存中有没有防止缓存击穿,然后创建ListenerRetriever的对象,然后通过retrieveApplicationListeners方法搜寻listenser:
private Collection
ResolvableType eventType, @Nullable Class> sourceType, @Nullable ListenerRetriever retriever) {
List
Set
Set
synchronized (this.retrievalMutex) {
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(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) {
if (beanFactory.isSingleton(listenerBeanName)) {
retriever.applicationListeners.add(listener);
}
else {
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);
if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
retriever.applicationListeners.clear();
retriever.applicationListeners.addAll(allListeners);
}
return allListeners
}
首先把defaultRetriever中的listener加入listeners,defaultRetriever中的listener是在EventPublishingRunListener中的构造方法中赋值上文已经
研究过了,因为暂时没有赋值applicationListenerBeans所以listenerBeans的size为0
然后判断listener是否支持eventtype和sourcetype,如果支持则加入retriever的applicationListeners中并把listener加入allListeners中返回.
回到getApplicationListeners方法中,把new的retriever放入缓存中并放回listeners.
之后返回到 SimpleApplicationEventMulticaster 类的multicastEvent方法中,获取了所有listener后获取taskExecutor因为获取的executor是空的,所以
执行invokeListener(listener, event)方法调用各种listener的onApplicationEvent方法执行具体代码.
以上就是listener的的运行流程,需要考虑的问题有几个:
1.getApplicationListeners中获取的是Collection
这个问题产生是我的一个误区,我看到getRunListeners中获取的是SpringApplicationRunListener的对象下意识的一位后面所有用的都是这个对象,但其实
在后面只是在条用starting的时候用到这个对象,其他对象都是在EventPublishingRunListener的构造中this.initialMulticaster.addApplicationListener(listener)
方法中获取的,而这个listener是application.getListeners的集合中的元素,在前面研究的初始化流程中通过setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
赋值,确实是ApplicationListener的对象.
总结来说SpringApplicationRunListeners并不是具体的listener,而是包装了启动所需要的listener的一个类.
2.这一块儿代码最核心的设计模式是什么?
观察者模式.(定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.)