當SpringApplication初始化完畢后,就開始調用實際的run方法執行其他初始化了。
本地分析SpringApplicationRunListeners的初始化過程,源碼如下:
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
1.1 初始化EventPublishingRunListener
EventPublishingRunListener是SpringApplicationRunListener的實現,是實際用於發布SpringApplicationEvent類型的事件的實現類。點擊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根據對應的類型來讀取spring.factories中的實現:
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
需要注意的是除了類型參數(SpringApplicationRunListener),還包含已經初始化好的SpringApplication和String類。SpringApplication參數是為了獲取內部已通過spring.factories中讀取的Listener。
從之前的getSpringFactoriesInstances方法可知讀取到對應的EventPublishingRunListener實現后會對該實現類進行實例化,以下跟進EventPublishingRunListener的構造方法:
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
// 對initialMulticaster進行實例化
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// SpringApplication參數的作用體現出來了,用於遍歷listeners
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
}
這里將initialMulticaster變量進行初始化實例,最終通過該實例調用其抽象類AbstractApplicationEventMulticaster的addApplicationListener方法將SpringApplication初始化時的Listeners一個個加入到其中,點擊addApplicationListener跟進源碼:
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
private Object retrievalMutex = this.defaultRetriever;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
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();
}
}
}
private class ListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
......
}
在ListenerRetriever中維護着一個Set集合,該Set集合存放着從SpringApplication中獲取到的listeners集合,它的作用在於后續遍歷監聽器,判斷監聽器是否支持某個事件提供了數據源。
1.2 篩選支持指定事件的Listener
當EventPublishingRunListener初始化完成后,調用其starting方法開始根據指定的事件遍歷Listener是否支持該指定事件:
class SpringApplicationRunListeners {
void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
}
可以看出該指定事件為ApplicationStartingEvent,需要注意的是本次判斷一個listener是否支持某個事件指的就是ApplicationStartingEvent。
點擊multicastEvent跟進源碼,這里主要將對應的事件包裝成ResolvableType類型,遍歷listeners,對於支持ApplicationStartingEvent事件的listener調用其內部的onApplicationEvent方法:
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Override
public void multicastEvent(ApplicationEvent event) {
// 這里將event包裝成ResolvableType
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 獲取對事件支持的監聽器,不支持的不會出現在一下的循環體內
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
}
獲取對事件支持的監聽器,核心方法在於getApplicationListeners,這里遍歷了Listeners,判斷每個Listener是否支持指定的事件(即ApplicationStartingEvent),點擊getApplicationListeners跟進源碼:
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
@Nullable
private ClassLoader beanClassLoader;
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作為緩存key
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// 從緩存獲取支持事件的監聽器,由於之前沒有初始化過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)))) {
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 {
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
}
啟動時的初始化是不存在緩存的,所以進入retrieveApplicationListeners方法跟進源碼:
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
private Object retrievalMutex = this.defaultRetriever;
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.retrievalMutex) {
// defaultRetriever就是初始化EventPublishingRunListener時調用父類AbstractApplicationEventMulticaster的addApplicationListener方法對其進行初始化
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
// 遍歷每個監聽器,之前說的ListenerRetriever中維護着一個Set集合就是為此提供了數據源
for (ApplicationListener<?> listener : listeners) {
// 實際判斷監聽器是否支持事件的方法
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
...... // 省略
// 對監聽器進行排序,為了監聽器的執行順序
AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
retriever.applicationListeners.clear();
retriever.applicationListeners.addAll(allListeners);
}
return allListeners;
}
}
最終判斷監聽器是否支持某種事件類型是通過supportsEvent方法來進行,點擊supportsEvent跟進源碼:
public abstract class AbstractApplicationEventMulticasterimplements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
// 判斷listener是否屬於GenericApplicationListener類型轉換不同的適配,用於根據不同適配調用對應的用於判斷是否支持某個事件類型的supportsEventType方法
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
}
這里分為以下兩種情況:
- 若屬於GenericApplicationListener的子類則通過GenericApplicationListener父類調用自身的supportsEventType方法判斷自己是否支持此事件
- 若不屬於GenericApplicationListener的子類則通過GenericApplicationListenerAdapter統一判斷listener是否支持此事件
1.2.1 情況一:屬於GenericApplicationListener的子類
以LoggingApplicationListener為例,它是屬於GenericApplicationListener的子類,類簡要定義如下:
public class LoggingApplicationListener implements GenericApplicationListener {
private static final Class<?>[] EVENT_TYPES = {
ApplicationStartingEvent.class
, ApplicationEnvironmentPreparedEvent.class
, ApplicationPreparedEvent.class
, ContextClosedEvent.class
, ApplicationFailedEvent.class };
private static final Class<?>[] SOURCE_TYPES = { SpringApplication.class, ApplicationContext.class };
@Override
public boolean supportsEventType(ResolvableType resolvableType) {
// 通過父類調用本身的supportsEventType方法校驗支持的事件
return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
}
// 最終的校驗方法
private boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
if (type != null) {
for (Class<?> supportedType : supportedTypes) {
if (supportedType.isAssignableFrom(type)) {
return true;
}
}
}
return false;
}
}
從常量EVENT_TYPES定義的該listener支持的事件類型就可以判斷出它是支持ApplicationStartingEvent事件。
1.2.2 情況二:不屬於GenericApplicationListener的子類
不屬於GenericApplicationListener的子類則是實例化出new GenericApplicationListenerAdapter(listener)),進入GenericApplicationListenerAdapter構造:
public class GenericApplicationListenerAdapter implements GenericApplicationListener, SmartApplicationListener {
private final ApplicationListener<ApplicationEvent> delegate;
@Nullable
private final ResolvableType declaredEventType;
public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
Assert.notNull(delegate, "Delegate listener must not be null");
this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
// 這里解析出listener的實際泛型事件並包裝成ResolvableType,待后續通過該adapter調用其supportsEventType判斷是否支持時間時有用
this.declaredEventType = resolveDeclaredEventType(this.delegate);
}
@Nullable
private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) {
ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass());
if (declaredEventType == null || declaredEventType.isAssignableFrom(ApplicationEvent.class)) {
Class<?> targetClass = AopUtils.getTargetClass(listener);
if (targetClass != listener.getClass()) {
declaredEventType = resolveDeclaredEventType(targetClass);
}
}
return declaredEventType;
}
@Nullable
static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
ResolvableType eventType = eventTypeCache.get(listenerType);
if (eventType == null) {
eventType = ResolvableType.forClass(listenerType).as(ApplicationListener.class).getGeneric();
eventTypeCache.put(listenerType, eventType);
}
return (eventType != ResolvableType.NONE ? eventType : null);
}
}
可以看出這種方式就是對於每個不屬於GenericApplicationListener子類的listener都創建一個GenericApplicationListenerAdapter對象,根據listener獲取其支持的事件並對內部屬性進行初始化;
后續調用GenericApplicationListenerAdapter對象的supportsEventType方法判斷是否支持某個事件時GenericApplicationListenerAdapter對象就能獲取到該listener已解析過的支持的事件類型:
public class GenericApplicationListenerAdapter implements GenericApplicationListener, SmartApplicationListener {
@Override
@SuppressWarnings("unchecked")
public boolean supportsEventType(ResolvableType eventType) {
// 根據是否是屬於SmartApplicationListener類型的實例執行不同的判斷
if (this.delegate instanceof SmartApplicationListener) {
Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
}
else {
return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
}
}
}
可以看出這里又分為兩種情況:
- listener屬於SmartApplicationListener的子類
- listener不屬於SmartApplicationListener的子類
不屬於SmartApplicationListener子類
若listener非SmartApplicationListener子類則進入else方法,else方法體中的declaredEventType屬性是在初始化GenericApplicationListenerAdapter時就被解析出了事件類型所包裝的對象。
例如CloudFoundryVcapEnvironmentPostProcessor,它的定義如下:
public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered, ApplicationListener<ApplicationPreparedEvent> {}
所以以上的declaredEventType屬性在CloudFoundryVcapEnvironmentPostProcessor被解析事件類型后解析出來的為ApplicationPreparedEvent事件,最終isAssignableFrom方法是這么判斷該listener是否支持事件:
if (ourResolved == null) {
// listener支持的事件,CloudFoundryVcapEnvironmentPostProcessor支持ApplicationPreparedEvent事件
ourResolved = resolve(Object.class);
}
Class<?> otherResolved = other.toClass();
// otherResolved是實際需要支持的事件,這里初始化的事件為ApplicationStartingEvent
if (exactMatch ? !ourResolved.equals(otherResolved) : !ClassUtils.isAssignable(ourResolved, otherResolved)) {
return false;
}
所以CloudFoundryVcapEnvironmentPostProcessor並不支持ApplicationStartingEvent事件,所以本次初始化它的onApplicationEvent並不會得到執行。
屬於SmartApplicationListener子類
若listener屬於SmartApplicationListener子類則進入if方法,例如ConfigFileApplicationListener,它的簡要類定義如下:
public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
|| ApplicationPreparedEvent.class.isAssignableFrom(eventType);
}
}
對於屬於SmartApplicationListener的子類,則是將listener轉換成父類,通過調用父類的supportsEventType方法達到調用自身supportsEventType方法來做判斷,但是從ConfigFileApplicationListener的supportsEventType方法來看明細它是不支持ApplicationStartingEvent。
1.3 Listner排序並發布
對於上述篩選出來的listener,為了確保其執行順序則對它進行排序:
AnnotationAwareOrderComparator.sort(allListeners);
這種排序已經看到在許多地方出現過,比如初始化SpringApplication的Initializers和Listeners,所以這里不再詳細說明。
1.3.1 發布Listener
以下是篩選了支持指定事件的Listener:
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
}
由於executor為空,所以這里都是調用了else方法提內的invokeListener方法。
對於listener來說,每個listener都會實現ApplicationListener或者其子接口SmartApplicationListener,所以它們都會重寫onApplicationEvent方法:
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 最終還是調用每個支持該事件的listener中的重寫了父類的onApplicationEvent方法
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
}
1.3.2 發布Listener說明
貫穿整個SpringBoot的啟動過程,會有多次類似上面獲取監聽器所支持的事件進行發布,區別在於不同的初始化流程傳入的需要支持的事件類型不同, 以下是EventPublishingRunListener的源碼:
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
@Override
public void started(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
}
@Override
public void running(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
}
......
}