springboot源碼解析(一):啟動(dòng)過程
1、springboot的入口程序
@SpringBootApplication
public class StartupApplication {
public static void main(String[] args) {
SpringApplication.run(StartupApplication.class, args);
}
}
當(dāng)程序開始執(zhí)行之后,會(huì)調(diào)用SpringApplication的構(gòu)造方法,進(jìn)行某些初始參數(shù)的設(shè)置
//創(chuàng)建一個(gè)新的實(shí)例,這個(gè)應(yīng)用程序的上下文將要從指定的來源加載Bean
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//資源初始化資源加載器,默認(rèn)為null
this.resourceLoader = resourceLoader;
//斷言主要加載資源類不能為 null,否則報(bào)錯(cuò)
Assert.notNull(primarySources, "PrimarySources must not be null");
//初始化主要加載資源類集合并去重
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//推斷當(dāng)前 WEB 應(yīng)用類型,一共有三種:NONE,SERVLET,REACTIVE
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//設(shè)置應(yīng)用上線文初始化器,從"META-INF/spring.factories"讀取ApplicationContextInitializer類的實(shí)例名稱集合并去重,并進(jìn)行set去重。(一共7個(gè))
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//設(shè)置監(jiān)聽器,從"META-INF/spring.factories"讀取ApplicationListener類的實(shí)例名稱集合并去重,并進(jìn)行set去重。(一共11個(gè))
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推斷主入口應(yīng)用類,通過當(dāng)前調(diào)用棧,獲取Main方法所在類,并賦值給mainApplicationClass
this.mainApplicationClass = deduceMainApplicationClass();
}
在上述構(gòu)造方法中,有一個(gè)判斷應(yīng)用類型的方法,用來判斷當(dāng)前應(yīng)用程序的類型:
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
//WebApplicationType的類型
public enum WebApplicationType {
/**
* The application should not run as a web application and should not start an
* embedded web server.
* 非web項(xiàng)目
*/
NONE,
/**
* The application should run as a servlet-based web application and should start an
* embedded servlet web server.
* servlet web 項(xiàng)目
*/
SERVLET,
/**
* The application should run as a reactive web application and should start an
* embedded reactive web server.
* 響應(yīng)式 web 項(xiàng)目
*/
REACTIVE;
springboot啟動(dòng)的運(yùn)行方法,可以看到主要是各種運(yùn)行環(huán)境的準(zhǔn)備工作
public ConfigurableApplicationContext run(String... args) {
//1、創(chuàng)建并啟動(dòng)計(jì)時(shí)監(jiān)控類
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//2、初始化應(yīng)用上下文和異常報(bào)告集合
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//3、設(shè)置系統(tǒng)屬性“java.awt.headless”的值,默認(rèn)為true,用于運(yùn)行headless服務(wù)器,進(jìn)行簡(jiǎn)單的圖像處理,多用于在缺少顯示屏、鍵盤或者鼠標(biāo)時(shí)的系統(tǒng)配置,很多監(jiān)控工具如jconsole 需要將該值設(shè)置為true
configureHeadlessProperty();
//4、創(chuàng)建所有spring運(yùn)行監(jiān)聽器并發(fā)布應(yīng)用啟動(dòng)事件,簡(jiǎn)單說的話就是獲取SpringApplicationRunListener類型的實(shí)例(EventPublishingRunListener對(duì)象),并封裝進(jìn)SpringApplicationRunListeners對(duì)象,然后返回這個(gè)SpringApplicationRunListeners對(duì)象。說的再簡(jiǎn)單點(diǎn),getRunListeners就是準(zhǔn)備好了運(yùn)行時(shí)監(jiān)聽器EventPublishingRunListener。
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
//5、初始化默認(rèn)應(yīng)用參數(shù)類
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//6、根據(jù)運(yùn)行監(jiān)聽器和應(yīng)用參數(shù)來準(zhǔn)備spring環(huán)境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//將要忽略的bean的參數(shù)打開
configureIgnoreBeanInfo(environment);
//7、創(chuàng)建banner打印類
Banner printedBanner = printBanner(environment);
//8、創(chuàng)建應(yīng)用上下文,可以理解為創(chuàng)建一個(gè)容器
context = createApplicationContext();
//9、準(zhǔn)備異常報(bào)告器,用來支持報(bào)告關(guān)于啟動(dòng)的錯(cuò)誤
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//10、準(zhǔn)備應(yīng)用上下文,該步驟包含一個(gè)非常關(guān)鍵的操作,將啟動(dòng)類注入容器,為后續(xù)開啟自動(dòng)化提供基礎(chǔ)
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//11、刷新應(yīng)用上下文
refreshContext(context);
//12、應(yīng)用上下文刷新后置處理,做一些擴(kuò)展功能
afterRefresh(context, applicationArguments);
//13、停止計(jì)時(shí)監(jiān)控類
stopWatch.stop();
//14、輸出日志記錄執(zhí)行主類名、時(shí)間信息
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//15、發(fā)布應(yīng)用上下文啟動(dòng)監(jiān)聽事件
listeners.started(context);
//16、執(zhí)行所有的Runner運(yùn)行器
callRunners(context, applicationArguments);
}catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
//17、發(fā)布應(yīng)用上下文就緒事件
listeners.running(context);
}catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
//18、返回應(yīng)用上下文
return context;
}
下面詳細(xì)介紹各個(gè)啟動(dòng)的環(huán)節(jié):
1、創(chuàng)建并啟動(dòng)計(jì)時(shí)監(jiān)控類,可以看到記錄當(dāng)前任務(wù)的名稱,默認(rèn)是空字符串,然后記錄當(dāng)前springboot應(yīng)用啟動(dòng)的開始時(shí)間。
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//詳細(xì)源代碼
public void start() throws IllegalStateException {
start("");
}
public void start(String taskName) throws IllegalStateException {
if (this.currentTaskName != null) {
throw new IllegalStateException("Can't start StopWatch: it's already running");
}
this.currentTaskName = taskName;
this.startTimeNanos = System.nanoTime();
}
2、初始化應(yīng)用上下文和異常報(bào)告集合
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
3、設(shè)置系統(tǒng)屬性java.awt.headless的值:
/*
java.awt.headless模式是在缺少顯示屏、鍵盤或者鼠標(biāo)的系統(tǒng)配置
當(dāng)配置了如下屬性之后,應(yīng)用程序可以執(zhí)行如下操作:
1、創(chuàng)建輕量級(jí)組件
2、收集關(guān)于可用的字體、字體指標(biāo)和字體設(shè)置的信息
3、設(shè)置顏色來渲染準(zhǔn)備圖片
4、創(chuàng)造和獲取圖像,為渲染準(zhǔn)備圖片
5、使用java.awt.PrintJob,java.awt.print.*和javax.print.*類里的方法進(jìn)行打印
*/
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
4、創(chuàng)建所有spring運(yùn)行監(jiān)聽器并發(fā)布應(yīng)用啟動(dòng)事件
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
//創(chuàng)建spring監(jiān)聽器
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
}
//循環(huán)遍歷獲取監(jiān)聽器
void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
//此處的監(jiān)聽器可以看出是事件發(fā)布監(jiān)聽器,主要用來發(fā)布啟動(dòng)事件
@Override
public void starting() {
//這里是創(chuàng)建application事件‘a(chǎn)pplicationStartingEvent’
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
//applicationStartingEvent是springboot框架最早執(zhí)行的監(jiān)聽器,在該監(jiān)聽器執(zhí)行started方法時(shí),會(huì)繼續(xù)發(fā)布事件,主要是基于spring的事件機(jī)制
@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) {
//異步發(fā)送事件
executor.execute(() -> invokeListener(listener, event));
}
else {
//同步發(fā)送事件
invokeListener(listener, event);
}
}
}
5、初始化默認(rèn)應(yīng)用參數(shù)類
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
public DefaultApplicationArguments(String... args) {
Assert.notNull(args, "Args must not be null");
this.source = new Source(args);
this.args = args;
}
6、根據(jù)運(yùn)行監(jiān)聽器和應(yīng)用參數(shù)來準(zhǔn)備spring環(huán)境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//詳細(xì)環(huán)境的準(zhǔn)備
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 獲取或者創(chuàng)建應(yīng)用環(huán)境
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置應(yīng)用環(huán)境,配置propertySource和activeProfiles
configureEnvironment(environment, applicationArguments.getSourceArgs());
//listeners環(huán)境準(zhǔn)備,廣播ApplicationEnvironmentPreparedEvent
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(environment);
//將環(huán)境綁定給當(dāng)前應(yīng)用程序
bindToSpringApplication(environment);
//對(duì)當(dāng)前的環(huán)境類型進(jìn)行判斷,如果不一致進(jìn)行轉(zhuǎn)換
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
//配置propertySource對(duì)它自己的遞歸依賴
ConfigurationPropertySources.attach(environment);
return environment;
}
// 獲取或者創(chuàng)建應(yīng)用環(huán)境,根據(jù)應(yīng)用程序的類型可以分為servlet環(huán)境、標(biāo)準(zhǔn)環(huán)境(特殊的非web環(huán)境)和響應(yīng)式環(huán)境
private ConfigurableEnvironment getOrCreateEnvironment() {
//存在則直接返回
if (this.environment != null) {
return this.environment;
}
//根據(jù)webApplicationType創(chuàng)建對(duì)應(yīng)的Environment
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
//配置應(yīng)用環(huán)境
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
//配置property sources
configurePropertySources(environment, args);
//配置profiles
configureProfiles(environment, args);
}
7、創(chuàng)建banner的打印類
Banner printedBanner = printBanner(environment);//打印類的詳細(xì)操作過程private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Banner.Mode.OFF) { return null; } ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader : new DefaultResourceLoader(getClassLoader()); SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner); if (this.bannerMode == Mode.LOG) { return bannerPrinter.print(environment, this.mainApplicationClass, logger); } return bannerPrinter.print(environment, this.mainApplicationClass, System.out); }
8、創(chuàng)建應(yīng)用的上下文:根據(jù)不同哦那個(gè)的應(yīng)用類型初始化不同的上下文應(yīng)用類
context = createApplicationContext();protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch (this.webApplicationType) { case SERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }
9、準(zhǔn)備異常報(bào)告器
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context);private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
10、準(zhǔn)備應(yīng)用上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //應(yīng)用上下文的environment context.setEnvironment(environment); //應(yīng)用上下文后處理 postProcessApplicationContext(context); //為上下文應(yīng)用所有初始化器,執(zhí)行容器中的applicationContextInitializer(spring.factories的實(shí)例),將所有的初始化對(duì)象放置到context對(duì)象中 applyInitializers(context); //觸發(fā)所有SpringApplicationRunListener監(jiān)聽器的ContextPrepared事件方法。添加所有的事件監(jiān)聽器 listeners.contextPrepared(context); //記錄啟動(dòng)日志 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // 注冊(cè)啟動(dòng)參數(shù)bean,將容器指定的參數(shù)封裝成bean,注入容器 ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); //設(shè)置banner if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // 加載所有資源,指的是啟動(dòng)器指定的參數(shù) Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); //將bean加載到上下文中 load(context, sources.toArray(new Object[0])); //觸發(fā)所有springapplicationRunListener監(jiān)聽器的contextLoaded事件方法, listeners.contextLoaded(context); }------------------- //這里沒有做任何的處理過程,因?yàn)閎eanNameGenerator和resourceLoader默認(rèn)為空,可以方便后續(xù)做擴(kuò)展處理 protected void postProcessApplicationContext(ConfigurableApplicationContext context) { if (this.beanNameGenerator != null) { context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader != null) { if (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); } if (context instanceof DefaultResourceLoader) { ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader()); } } if (this.addConversionService) { context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance()); } }--------------------- //將啟動(dòng)器類加載到spring容器中,為后續(xù)的自動(dòng)化配置奠定基礎(chǔ),之前看到的很多注解也與此相關(guān) protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources)); } BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator != null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader != null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment != null) { loader.setEnvironment(this.environment); } loader.load(); }--------------------- //springboot會(huì)優(yōu)先選擇groovy加載方式,找不到在選擇java方式 private int load(Class<?> source) { if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { // Any GroovyLoaders added in beans{} DSL can contribute beans here GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); load(loader); } if (isComponent(source)) { this.annotatedReader.register(source); return 1; } return 0; }
11、刷新應(yīng)用上下文
refreshContext(context);private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } }------------ public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //刷新上下文環(huán)境,初始化上下文環(huán)境,對(duì)系統(tǒng)的環(huán)境變量或者系統(tǒng)屬性進(jìn)行準(zhǔn)備和校驗(yàn) prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //初始化beanfactory,解析xml,相當(dāng)于之前的xmlBeanfactory操作 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //為上下文準(zhǔn)備beanfactory,對(duì)beanFactory的各種功能進(jìn)行填充,如@autowired,設(shè)置spel表達(dá)式解析器,設(shè)置編輯注冊(cè)器,添加applicationContextAwareprocessor處理器等等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //提供子類覆蓋的額外處理,即子類處理自定義的beanfactorypostProcess postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //激活各種beanfactory處理器 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //注冊(cè)攔截bean創(chuàng)建的bean處理器,即注冊(cè)beanPostProcessor registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //初始化上下文中的資源文件如國(guó)際化文件的處理 initMessageSource(); // Initialize event multicaster for this context. //初始化上下文事件廣播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //給子類擴(kuò)展初始化其他bean onRefresh(); // Check for listener beans and register them. //在所有的bean中查找listener bean,然后 注冊(cè)到廣播器中 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //初始化剩余的非懶惰的bean,即初始化非延遲加載的bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //發(fā)完成刷新過程,通知聲明周期處理器刷新過程,同時(shí)發(fā)出ContextRefreshEvent通知?jiǎng)e人 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
12、應(yīng)用上下文刷新后置處理
afterRefresh(context, applicationArguments);//當(dāng)前方法的代碼是空的,可以做一些自定義的后置處理操作protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { }
13、停止計(jì)時(shí)監(jiān)控類:計(jì)時(shí)監(jiān)聽器停止,并統(tǒng)計(jì)一些任務(wù)執(zhí)行信息
stopWatch.stop();public void stop() throws IllegalStateException { if (this.currentTaskName == null) { throw new IllegalStateException("Can't stop StopWatch: it's not running"); } long lastTime = System.nanoTime() - this.startTimeNanos; this.totalTimeNanos += lastTime; this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime); if (this.keepTaskList) { this.taskList.add(this.lastTaskInfo); } ++this.taskCount; this.currentTaskName = null; }
14、輸出日志記錄執(zhí)行主類名、時(shí)間信息
if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}
15、發(fā)布應(yīng)用上下文啟動(dòng)完成事件:觸發(fā)所有SpringapplicationRunListener監(jiān)聽器的started事件方法
listeners.started(context); void started(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.started(context); } }
16、執(zhí)行所有Runner執(zhí)行器:執(zhí)行所有applicationRunner和CommandLineRunner兩種運(yùn)行器
callRunners(context, applicationArguments);private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
17、發(fā)布應(yīng)用上下文就緒事件:觸發(fā)所有springapplicationRunnListener將挺起的running事件方法
listeners.running(context);void running(ConfigurableApplicationContext context) { for (SpringApplicationRunListener listener : this.listeners) { listener.running(context); } }
18、返回應(yīng)用上下文
return context;
注意:
整個(gè)springboot框架中獲取factorys文件的方式統(tǒng)一如下:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {});}-------------------------------------private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances;}----------------------------- public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { String factoryTypeName = factoryType.getName(); return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList()); } private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = cache.get(classLoader); if (result != null) { return result; } try { Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); result = new LinkedMultiValueMap<>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); for (Map.Entry<?, ?> entry : properties.entrySet()) { String factoryTypeName = ((String) entry.getKey()).trim(); for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) { result.add(factoryTypeName, factoryImplementationName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } }------------------------- private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) { List<T> instances = new ArrayList<>(names.size()); for (String name : names) { try { //裝載class文件到內(nèi)存 Class<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass); Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); //通過反射創(chuàng)建實(shí)例 T instance = (T) BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); } } return instances; }
spring.factory文件中的類的作用:
# PropertySource Loaders 屬性文件加載器org.springframework.boot.env.PropertySourceLoader=\# properties文件加載器org.springframework.boot.env.PropertiesPropertySourceLoader,\# yaml文件加載器org.springframework.boot.env.YamlPropertySourceLoader# Run Listeners 運(yùn)行時(shí)的監(jiān)聽器org.springframework.boot.SpringApplicationRunListener=\# 程序運(yùn)行過程中所有監(jiān)聽通知都是通過此類來進(jìn)行回調(diào)org.springframework.boot.context.event.EventPublishingRunListener# Error Reporters 錯(cuò)誤報(bào)告器org.springframework.boot.SpringBootExceptionReporter=\org.springframework.boot.diagnostics.FailureAnalyzers# Application Context Initializersorg.springframework.context.ApplicationContextInitializer=\# 報(bào)告spring容器的一些常見的錯(cuò)誤配置org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\# 設(shè)置spring應(yīng)用上下文的IDorg.springframework.boot.context.ContextIdApplicationContextInitializer,\# 使用環(huán)境屬性context.initializer.classes指定初始化器進(jìn)行初始化規(guī)則org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\# 將內(nèi)置servlet容器實(shí)際使用的監(jiān)聽端口寫入到environment環(huán)境屬性中org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer# Application Listenersorg.springframework.context.ApplicationListener=\# 應(yīng)用上下文加載完成后對(duì)緩存做清除工作,響應(yīng)事件ContextRefreshEventorg.springframework.boot.ClearCachesApplicationListener,\# 監(jiān)聽雙親應(yīng)用上下文的關(guān)閉事件并往自己的孩子應(yīng)用上下文中傳播,相關(guān)事件ParentContextAvailableEvent/ContextClosedEventorg.springframework.boot.builder.ParentContextCloserApplicationListener,\org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\# 如果系統(tǒng)文件編碼和環(huán)境變量中指定的不同則終止應(yīng)用啟動(dòng)。具體的方法是比較系統(tǒng)屬性file.encoding和環(huán)境變量spring.mandatory-file-encoding是否相等(大小寫不敏感)。org.springframework.boot.context.FileEncodingApplicationListener,\# 根據(jù)spring.output.ansi.enabled參數(shù)配置AnsiOutputorg.springframework.boot.context.config.AnsiOutputApplicationListener,\# EnvironmentPostProcessor,從常見的那些約定的位置讀取配置文件,比如從以下目錄讀取#application.properties,application.yml等配置文件:# classpath:# file:.# classpath:config# file:./config/:# 也可以配置成從其他指定的位置讀取配置文件org.springframework.boot.context.config.ConfigFileApplicationListener,\# 監(jiān)聽到事件后轉(zhuǎn)發(fā)給環(huán)境變量context.listener.classes指定的那些事件監(jiān)聽器org.springframework.boot.context.config.DelegatingApplicationListener,\# 一個(gè)SmartApplicationListener,對(duì)環(huán)境就緒事件ApplicationEnvironmentPreparedEvent/應(yīng)用失敗事件ApplicationFailedEvent做出響應(yīng),往日志DEBUG級(jí)別輸出TCCL(thread context class loader)的classpath。org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\# 檢測(cè)正在使用的日志系統(tǒng),默認(rèn)時(shí)logback,,此時(shí)日志系統(tǒng)還沒有初始化org.springframework.boot.context.logging.LoggingApplicationListener,\# 使用一個(gè)可以和Spring Boot可執(zhí)行jar包配合工作的版本替換liquibase ServiceLocatororg.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener# Environment Post Processorsorg.springframework.boot.env.EnvironmentPostProcessor=\org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor# Failure Analyzersorg.springframework.boot.diagnostics.FailureAnalyzer=\org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer# FailureAnalysisReportersorg.springframework.boot.diagnostics.FailureAnalysisReporter=\org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter# Initializersorg.springframework.context.ApplicationContextInitializer=\org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener# Application Listenersorg.springframework.context.ApplicationListener=\# 另外單獨(dú)啟動(dòng)一個(gè)線程實(shí)例化并調(diào)用run方法,包括驗(yàn)證器、消息轉(zhuǎn)換器等org.springframework.boot.autoconfigure.BackgroundPreinitializer# Auto Configuration Import Listenersorg.springframework.boot.autoconfigure.AutoConfigurationImportListener=\org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener# Auto Configuration Import Filtersorg.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\org.springframework.boot.autoconfigure.condition.OnBeanCondition,\org.springframework.boot.autoconfigure.condition.OnClassCondition,\org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveRestClientAutoConfiguration,\org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration# Failure analyzersorg.springframework.boot.diagnostics.FailureAnalyzer=\org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer# Template availability providersorg.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
注意:
整個(gè)springboot框架中獲取factorys文件的方式統(tǒng)一如下:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
-------------------------------------
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
-----------------------------
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
-------------------------
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
//裝載class文件到內(nèi)存
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
//通過反射創(chuàng)建實(shí)例
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
spring.factory文件中的類的作用:
# PropertySource Loaders 屬性文件加載器
org.springframework.boot.env.PropertySourceLoader=\
# properties文件加載器
org.springframework.boot.env.PropertiesPropertySourceLoader,\
# yaml文件加載器
org.springframework.boot.env.YamlPropertySourceLoader
# Run Listeners 運(yùn)行時(shí)的監(jiān)聽器
org.springframework.boot.SpringApplicationRunListener=\
# 程序運(yùn)行過程中所有監(jiān)聽通知都是通過此類來進(jìn)行回調(diào)
org.springframework.boot.context.event.EventPublishingRunListener
# Error Reporters 錯(cuò)誤報(bào)告器
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
# 報(bào)告spring容器的一些常見的錯(cuò)誤配置
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
# 設(shè)置spring應(yīng)用上下文的ID
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
# 使用環(huán)境屬性context.initializer.classes指定初始化器進(jìn)行初始化規(guī)則
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
# 將內(nèi)置servlet容器實(shí)際使用的監(jiān)聽端口寫入到environment環(huán)境屬性中
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
# 應(yīng)用上下文加載完成后對(duì)緩存做清除工作,響應(yīng)事件ContextRefreshEvent
org.springframework.boot.ClearCachesApplicationListener,\
# 監(jiān)聽雙親應(yīng)用上下文的關(guān)閉事件并往自己的孩子應(yīng)用上下文中傳播,相關(guān)事件ParentContextAvailableEvent/ContextClosedEvent
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
# 如果系統(tǒng)文件編碼和環(huán)境變量中指定的不同則終止應(yīng)用啟動(dòng)。具體的方法是比較系統(tǒng)屬性file.encoding和環(huán)境變量spring.mandatory-file-encoding是否相等(大小寫不敏感)。
org.springframework.boot.context.FileEncodingApplicationListener,\
# 根據(jù)spring.output.ansi.enabled參數(shù)配置AnsiOutput
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
# EnvironmentPostProcessor,從常見的那些約定的位置讀取配置文件,比如從以下目錄讀取#application.properties,application.yml等配置文件:
# classpath:
# file:.
# classpath:config
# file:./config/:
# 也可以配置成從其他指定的位置讀取配置文件
org.springframework.boot.context.config.ConfigFileApplicationListener,\
# 監(jiān)聽到事件后轉(zhuǎn)發(fā)給環(huán)境變量context.listener.classes指定的那些事件監(jiān)聽器
org.springframework.boot.context.config.DelegatingApplicationListener,\
# 一個(gè)SmartApplicationListener,對(duì)環(huán)境就緒事件ApplicationEnvironmentPreparedEvent/應(yīng)用失敗事件ApplicationFailedEvent做出響應(yīng),往日志DEBUG級(jí)別輸出TCCL(thread context class loader)的classpath。
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
# 檢測(cè)正在使用的日志系統(tǒng),默認(rèn)時(shí)logback,,此時(shí)日志系統(tǒng)還沒有初始化
org.springframework.boot.context.logging.LoggingApplicationListener,\
# 使用一個(gè)可以和Spring Boot可執(zhí)行jar包配合工作的版本替換liquibase ServiceLocator
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer
# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
# 另外單獨(dú)啟動(dòng)一個(gè)線程實(shí)例化并調(diào)用run方法,包括驗(yàn)證器、消息轉(zhuǎn)換器等
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
