SpringBoot原始碼學習(更新中)
阿新 • • 發佈:2019-02-12
最近在專案中運用了Springboot,簡單的學習了簡單的使用,於是想去看看原始碼是如何實現的。
自己也是第一次嘗試看原始碼,結合了網上的東西和自己的理解,在部落格裡寫點東西,做做積累, 如果其中哪些地方解釋有問題,
歡迎老司機指出
參考文章:
1.https://my.oschina.net/u/3081965/blog/916126
2.http://www.cfanz.cn/index.php?c=article&a=read&id=307782
首先不知道從哪裡入手,於是我從專案的啟動入口開始。
以下就是專案入口程式碼,很簡單,由於是在慕課網上學習的,這裡的報名就直接寫imooc了(這個為對應springboot的學習地址:http://www.imooc.com/learn/767)
這邊的spring-boot版本為1.4.7
package com.imooc; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GirlApplication { public static void main(String[] args) { SpringApplication.run(GirlApplication.class, args); } }
@SpringBootApplication 註解暫時不講,先從下面這個方法開始講起
SpringApplication.run(GirlApplication.class, args);
點選進去可以看到
/** * Static helper that can be used to run a {@link SpringApplication} from the * specified source using default settings. * @param source the source to load * @param args the application arguments (usually passed from a Java main method) * @return the running {@link ApplicationContext} */ public static ConfigurableApplicationContext run(Object source, String... args) {
//第一次進入到達這裡
return run(new Object[] { source }, args);
}
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param sources the sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
//上面方法後進入這裡
return new SpringApplication(sources).run(args);
}
首先為第一步,第一步呼叫第二部的方法,這裡主要看下第二步。
第二步這邊分為兩個步驟去看,第一個步驟為呼叫SpringApplication類的構造方法建立物件,第二步為呼叫建立物件的run方法,這裡以這兩個步驟進行解讀。
構建物件:
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
* @param sources the bean sources
* @see #run(Object, String[])
* @see #SpringApplication(ResourceLoader, Object...)
*/
public SpringApplication(Object... sources) {
//呼叫初始化方法
initialize(sources);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
//將物件資源存放到sources這個linkedSet下,這裡的sources就是上訴的com.imooc.GirlController物件
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//這裡暫時沒有看懂,從字面上來看,是判斷是否有web環境
this.webEnvironment = deduceWebEnvironment();
//例項化Initializer,initializers成員變數,是一個ApplicationContextInitializer型別物件的集合。
//顧名思義,ApplicationContextInitializer是一個可以用來初始化ApplicationContext的介面。
//初始化ApplicationContext的Initializer程式
//boot包下的META-INF/spring.factories
0 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
1 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
2 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
3 = "org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer"
//autoconfigure下的META-INF/spring.factories
4 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
5 = "org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer"
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//例項化監聽器
//初始化 ApplicationListener boot下9個,autoconfigure一個
//0 = "org.springframework.boot.ClearCachesApplicationListener"
//1 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"
//2 = "org.springframework.boot.context.FileEncodingApplicationListener"//3 = "org.springframework.boot.context.config.AnsiOutputApplicationListener"
//4 = "org.springframework.boot.context.config.ConfigFileApplicationListener"
//5 = "org.springframework.boot.context.config.DelegatingApplicationListener"
//6 = "org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener"
//7 = "org.springframework.boot.logging.ClasspathLoggingApplicationListener"
//8 = "org.springframework.boot.logging.LoggingApplicationListener"
//9 = "org.springframework.boot.autoconfigure.BackgroundPreinitializer"setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//找出main方法的全類名並返回其例項並設定到SpringApplication的this.mainApplicationClass完成初始化
this.mainApplicationClass = deduceMainApplicationClass();
}
這裡附上deduceWebEnvironment()方法的實現,其中WEB_ENVIRONMENT_CLASSES的值為
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private boolean deduceWebEnvironment() {
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return false;
}
}
return true;
}
上面SpringApplication的初始化動作已經做完了,然後看下run方法裡做了哪些操作。
public ConfigurableApplicationContext run(String... args) {
//StopWatch是一個監視器,主要是用來記錄程式的執行時間,這裡是用來記錄程式啟動所需要的時間 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.started(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }