SpringBoot啟動分析2:SpringApplicationRunListeners初始化


當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));
	}

	......
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM