上篇回顧
上一篇初始化SpringApplication實(shí)例, 我們實(shí)例化了一個(gè)SpringApplication實(shí)例,整個(gè)流程共計(jì)4步
- 調(diào)用WebApplicationType.deduceFromClasspath方法, 獲取Web類型
- 通過getSpringFactoriesInstances()方法, 調(diào)用SpringFactoriesLoader.loadFactoryNames, 首先加載META-INF/spring.factories配置的類名到緩存中, 之后實(shí)例化了ApplicationContextInitializer的子類列表, 賦值給SpringApplication的initializers列表
- 通過getSpringFactoriesInstances()方法, 調(diào)用SpringFactoriesLoader.loadFactoryNames,從SpringFactoriesLoader的緩存中獲取并實(shí)例化ApplicationListener子類列表, 賦值SpringApplication的listeners列表
- 通過拋出一個(gè)RuntimeException, 遍歷其堆棧信息, 獲取到類名中包含main方法的類, 實(shí)例化這個(gè)類, 賦值給SpringApplication的mainApplicationClass對象
目錄
1. 發(fā)布啟動(dòng)事件ApplicationStartingEvent
????1.1 SpringApplicationRunListeners源碼
????1.2 EventPublishingRunListener源碼
????1.3 SimpleApplicationEventMulticaster源碼
2. 啟動(dòng)事件的監(jiān)聽器
????2.1 LoggingApplicationListener
????2.2 BackgroundPreinitializer
????2.3 DelegatingApplicationListener
????2.4 LiquibaseServiceLocatorApplicationListener
3. 總結(jié)
1. 發(fā)布啟動(dòng)事件ApplicationStartingEvent
調(diào)用getRunListeners()方法, 實(shí)例化一個(gè)SpringApplicationRunListeners對象, SpringApplicationRunListeners的構(gòu)造參數(shù)通過getSpringFactoriesInstances()方法獲得,這個(gè)方法在之前分析過了, 獲取的一個(gè)EventPublishingRunListener對象, 所以調(diào)用的是EventPublishingRunListener#starting()方法
public class SpringApplication {
//run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//本文分析的重點(diǎn),發(fā)布啟動(dòng)事件ApplicationStartingEvent
//獲取SpringApplicationRunListener的子類listener
SpringApplicationRunListeners listeners = getRunListeners(args);
//執(zhí)行其starting()方法
listeners.starting();
....
}
//獲取SpringApplicationRunListener的子類listener
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//調(diào)用getSpringFactoriesInstances方法
//獲取SpringApplicationRunListener的子類
//子類只有一個(gè),EventPublishingRunListener
//實(shí)例化了一個(gè)SpringApplicationRunListeners對象
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
}
1.1 SpringApplicationRunListeners源碼
SpringApplicationRunListeners是一個(gè)比較重要的類, 之后的代碼會(huì)經(jīng)常調(diào)用這個(gè)方法, 內(nèi)部封裝了一個(gè)SpringApplicationRunListener的list, 方便以后擴(kuò)展, 目前只有一個(gè)EventPublishingRunListener實(shí)例, 所以spring的事件都是由EventPublishingRunListener發(fā)布的
//SpringApplicationRunListeners部分源碼
class SpringApplicationRunListeners {
private final Log log;
//SpringApplicationRunListener的子類對象列表
//listener列表擴(kuò)展點(diǎn)
private final List<SpringApplicationRunListener> listeners;
SpringApplicationRunListeners(Log log,
Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
}
//發(fā)布啟動(dòng)事件
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
//目前調(diào)用EventPublishingRunListener#starting方法
listener.starting();
}
}
//其他事件都是相同的代碼
//....
}
1.2 EventPublishingRunListener源碼
EventPublishingRunListener是springboot的事件廣播器, 內(nèi)部封裝了一個(gè)SimpleApplicationEventMulticaster對象, 用來發(fā)布springboot加載過程中的各個(gè)事件
- 事件源SpringApplication對象
- 事件SpringApplicationEvent對象
- 事件發(fā)布器是EventPublishingRunListener, 正在的事件發(fā)布器是其內(nèi)部SimpleApplicationEventMulticaster成員變量
- 事件監(jiān)聽器SpringApplication維護(hù)的listeners, 調(diào)用AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent, ResolvableType)篩選出支持ApplicationEvent的listeners
//EventPublishingRunListener部分源碼
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
//SpringApplication對象
private final SpringApplication application;
//命令函參數(shù)
private final String[] args;
//事件廣播器
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 通過application.getListeners(),獲取到Listener列表
// ConfigFileApplicationListener
// AnsiOutputApplicationListener
// LoggingApplicationListener
// ClasspathLoggingApplicationListener
// BackgroundPreinitializer
// DelegatingApplicationListener
// ParentContextCloserApplicationListener
// ClearCachesApplicationListener
// FileEncodingApplicationListener
// LiquibaseServiceLocatorApplicationListener
for (ApplicationListener<?> listener : application.getListeners()) {
//將listener添加到事件廣播器initialMulticaster
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public void starting() {
// 廣播器廣播ApplicationStartingEvent事件
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
//其他事件發(fā)布都是相同的代碼
//...
}
1.3 SimpleApplicationEventMulticaster源碼
springboot默認(rèn)事件廣播器, 有三個(gè)重要方法, 用于發(fā)布spring啟動(dòng)過程中的各個(gè)事件
- addApplicationListener() 添加監(jiān)聽器listener
- multicastEvent() 廣播spring事件
- invokeListener() 實(shí)現(xiàn)每個(gè)listener的onApplicationEvent()方法
父類AbstractApplicationEventMulticaster
封裝了四個(gè)重要方法:
- addApplicationListener添加listener
- addApplicationListenerBean添加注入的listener bean名稱
- removeApplicationListener刪除listener
- removeApplicationListenerBean刪除注入的listener bean名稱
- getApplicationListeners()先從緩存retrieverCache獲取listener,如果緩存不存在, 封裝數(shù)據(jù)放入緩存中, 增刪listener的時(shí)候, 緩存retrieverCache會(huì)被清空
//抽象事件廣播器
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
//監(jiān)聽器遍歷器
//成員變量applicationListeners Set維護(hù)了application中包含的listeners,
//成員變量applicationListenerBeans Set維護(hù)了注入的listener bean名稱
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
//調(diào)用getApplicationListeners()方法之后
//緩存spring事件以及對應(yīng)的listener列表
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
private Object retrievalMutex = this.defaultRetriever;
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.retrievalMutex) {
//監(jiān)聽器已經(jīng)被加載過,
//先執(zhí)行刪除操作,防止重復(fù)執(zhí)行
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
//清空緩存
this.retrieverCache.clear();
}
}
/**
* 獲取支持監(jiān)聽event的listener
* 這里使用了單例模式
*/
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
//嘗試從ConcurrentHashMap緩存中取出listener列表
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)))) {
//雙重檢查鎖定
//當(dāng)多線程訪問的時(shí)候,
//之前retriever多個(gè)線程否返回null,
//此時(shí)鎖住this.retrievalMutex
//防止多次實(shí)例化
synchronized (this.retrievalMutex) {
//再嘗試從cache中獲取
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
//生成Key和Value放入緩存中
retriever = new ListenerRetriever(true);
Collection<ApplicationListener<?>> listeners =
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
//沒有緩存ListenerRetriever,那么就不需要同步
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
//retrieveApplicationListeners方法中
//調(diào)用了supportsEvent方法
//supportsEvent使用了適配器模式
protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
}
SimpleApplicationEventMulticaster
廣播事件, 然后實(shí)現(xiàn)每個(gè)listener的onApplicationEvent()方法
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
@Nullable
private ErrorHandler errorHandler;
/**
* 構(gòu)造函數(shù)
* taskExecutor和errorHandler都是null
*/
public SimpleApplicationEventMulticaster() {
}
/**
* 廣播事件
* @param event 事件
* @param eventType 事件類型
*/
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//調(diào)用父類getApplicationListeners方法
//遍歷所有支持ApplicationStartingEvent事件的監(jiān)聽器
//LoggingApplicationListener
//BackgroundPreinitializer
//DelegatingApplicationListener
//LiquibaseServiceLocatorApplicationListener
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
//此時(shí)的executor為null
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
//調(diào)用listener
invokeListener(listener, event);
}
}
}
/**
* 具體調(diào)用監(jiān)聽器的方法
* @param listener 監(jiān)聽器
* @param event 事件
*/
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
//調(diào)用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.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
}
2. 啟動(dòng)事件的監(jiān)聽器
對Spring啟動(dòng)事件ApplicationStartingEvent感興趣的Listener:
- LoggingApplicationListener 日志監(jiān)聽器,配置日志
- BackgroundPreinitializer 后臺(tái)初始化器, 多線程加載耗時(shí)任務(wù)
- DelegatingApplicationListener 代理監(jiān)聽器, 繼續(xù)發(fā)布事件
- LiquibaseServiceLocatorApplicationListener 將liquibas替換為可以和spring配合工作的版本
2.1 LoggingApplicationListener部分代碼
獲取當(dāng)前應(yīng)用使用的日志系統(tǒng), 初始化loggingSystem, 調(diào)用loggingSystem的beforeInitialize方法, 開啟日志的準(zhǔn)備工作
public class LoggingApplicationListener implements GenericApplicationListener {
//處理starting事件
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
}
//日志系統(tǒng)準(zhǔn)備工作
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
//1.獲取模塊使用的日志系統(tǒng)
this.loggingSystem = LoggingSystem
.get(event.getSpringApplication().getClassLoader());
//2.日志系統(tǒng)準(zhǔn)備工作
//調(diào)用的是LogbackLoggingSystem#beforeInitialize
this.loggingSystem.beforeInitialize();
}
}
LoggingSystem
spring支持logback, Log4j, JDK logging, 有兩個(gè)重要方法
- get() 獲取應(yīng)用使用的日志系統(tǒng)
- beforeInitialize()獲取
springboot默認(rèn)使用logback, 也就是LogbackLoggingSystem
/**
*日志系統(tǒng)的父類
*/
public abstract class LoggingSystem {
public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
//Spring支持的幾種日志系統(tǒng)
private static final Map<String, String> SYSTEMS;
static {
Map<String, String> systems = new LinkedHashMap<>();
//1.logback
systems.put("ch.qos.logback.core.Appender",
"org.springframework.boot.logging.logback.LogbackLoggingSystem");
//2.Log4j
systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
//3.JDK logging
systems.put("java.util.logging.LogManager",
"org.springframework.boot.logging.java.JavaLoggingSystem");
SYSTEMS = Collections.unmodifiableMap(systems);
}
/**
* 判斷并返回模塊使用的日志系統(tǒng)
* 我們應(yīng)用使用的是logback
* @param classLoader 加載SpringApplication的classloader
*/
public static LoggingSystem get(ClassLoader classLoader) {
String loggingSystem = System.getProperty(SYSTEM_PROPERTY);
if (StringUtils.hasLength(loggingSystem)) {
if (NONE.equals(loggingSystem)) {
return new NoOpLoggingSystem();
}
return get(classLoader, loggingSystem);
}
//使用加載SpringApplication的classloader去加載支持的日志
//如果能加載一個(gè)或者多個(gè),返回第一個(gè)
//否則就拋出異常
return SYSTEMS.entrySet().stream()
.filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader))
.map((entry) -> get(classLoader, entry.getValue())).findFirst()
.orElseThrow(() -> new IllegalStateException(
"No suitable logging system located"));
}
}
/**
* logback日志系統(tǒng)
* 繼承了Sfl4j日志系統(tǒng)
*/
public class LogbackLoggingSystem extends Slf4JLoggingSystem {
@Override
public void beforeInitialize() {
//獲取LoggerContext
LoggerContext loggerContext = getLoggerContext();
//如果logger已經(jīng)被初始化,name直接返回
if (isAlreadyInitialized(loggerContext)) {
return;
}
//調(diào)用父類的beforeInitialize方法
//默認(rèn)使用debug模式
super.beforeInitialize();
loggerContext.getTurboFilterList().add(FILTER);
}
}
2.2 BackgroundPreinitializer
Spring會(huì)在項(xiàng)目啟動(dòng)的時(shí)候,默認(rèn)開啟線程加載一些耗時(shí)的任務(wù),這樣可以加快啟動(dòng)速度
@Order(LoggingApplicationListener.DEFAULT_ORDER + 1)
public class BackgroundPreinitializer
implements ApplicationListener<SpringApplicationEvent> {
//系統(tǒng)屬性用來配置是夠需要忽略預(yù)加載
public static final String IGNORE_BACKGROUNDPREINITIALIZER_PROPERTY_NAME = "spring.backgroundpreinitializer.ignore";
//預(yù)加載是否執(zhí)行,啟動(dòng)原子布爾類型,默認(rèn)為false
private static final AtomicBoolean preinitializationStarted = new AtomicBoolean(
false);
//同步工具
private static final CountDownLatch preinitializationComplete = new CountDownLatch(1);
}
2.3 DelegatingApplicationListener
擴(kuò)展點(diǎn), 可以繼續(xù)廣播事件, 查找屬性context.listener.classes對應(yīng)的listener名稱列表, 實(shí)例化代理監(jiān)聽器, 繼續(xù)廣播事件, 當(dāng)前應(yīng)用中沒有做任何操作
public class DelegatingApplicationListener
implements ApplicationListener<ApplicationEvent>, Ordered {
private static final String PROPERTY_NAME = "context.listener.classes";
//默認(rèn)為null
private SimpleApplicationEventMulticaster multicaster;
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
//監(jiān)聽到EnvironmentPreparedEvent事件
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) {
//再次發(fā)送事件
this.multicaster.multicastEvent(event);
}
}
//生成并返回Listener
private List<ApplicationListener<ApplicationEvent>> getListeners(
ConfigurableEnvironment environment) {
if (environment == null) {
return Collections.emptyList();
}
//獲取屬性名稱對應(yīng)的事件監(jiān)聽器名稱
String classNames = environment.getProperty(PROPERTY_NAME);
List<ApplicationListener<ApplicationEvent>> listeners = new ArrayList<>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.commaDelimitedListToSet(classNames)) {
try {
//反射生成對象
//放入監(jiān)聽器列表中
Class<?> clazz = ClassUtils.forName(className,
ClassUtils.getDefaultClassLoader());
Assert.isAssignable(ApplicationListener.class, clazz, "class ["
+ className + "] must implement ApplicationListener");
listeners.add((ApplicationListener<ApplicationEvent>) BeanUtils
.instantiateClass(clazz));
}
catch (Exception ex) {
throw new ApplicationContextException(
"Failed to load context listener class [" + className + "]",
ex);
}
}
}
AnnotationAwareOrderComparator.sort(listeners);
return listeners;
}
}
2.4 LiquibaseServiceLocatorApplicationListener
public class LiquibaseServiceLocatorApplicationListener
implements ApplicationListener<ApplicationStartingEvent> {
if (ClassUtils.isPresent("liquibase.servicelocator.CustomResolverServiceLocator",
event.getSpringApplication().getClassLoader())) {
//將liquibas替換為 可以和spring配合工作的版本
new LiquibasePresent().replaceServiceLocator();
}
}
3. 總結(jié)
- 首先調(diào)用getRunListeners()方法, 獲得一個(gè)SpringApplicationRunListeners對象,
- SpringApplicationRunListeners的成員變量listeners是通過getSpringFactoriesInstances()方法獲取的SpringApplicationRunListener子類列表
- 當(dāng)前只能獲取EventPublishingRunListener,
- 調(diào)用SpringApplicationRunListeners對象的starting()方法, 發(fā)布SpringApplication啟動(dòng)事件
- 內(nèi)部EventPublishingRunListener#starting()方法
- 最終調(diào)用SimpleApplicationEventMulticaster#multicastEvent()方法
- 發(fā)布了ApplicationStartingEvent事件, 最后執(zhí)行每個(gè)監(jiān)聽器的onApplicationEvent方法
- 對ApplicationStartingEvent事件感興趣的監(jiān)聽器
- LoggingApplicationListener 日志監(jiān)聽器,配置日志
- BackgroundPreinitializer 后臺(tái)初始化器, 多線程加載耗時(shí)任務(wù)
- DelegatingApplicationListener 代理監(jiān)聽器, 繼續(xù)發(fā)布事件
- LiquibaseServiceLocatorApplicationListener 將liquibas替換為可以和spring配合工作的版本
下一篇
我們將會(huì)在下一篇封裝命令行參數(shù)DefaultApplicationArguments, 繼續(xù)研究springboot的啟動(dòng)流程