一、springboot應用啓動源碼分析
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return (new SpringApplication(sources)).run(args);
}
【1】創建SpringApplication
對象
調用initialize(sources);
創建對象。流程:
private void initialize(Object[] sources) {
//1.保存主配置類
if(sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//2.判斷當前應用是否是一個web應用
this.webEnvironment = deduceWebEnvironment();
//3.從類路徑下找到META-INF/spring.factories配置的所有ApplicationContextInitializer,然後保存起來
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//4.從類路徑下找到META-INF/spring.factories配置的所有ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//5.從多個配置類中找到含有"main"的主配置類
this.mainApplicationClass = deduceMainApplicationClass();
}
有6個initializer:
可以找到的ApplicationListener:
【2】運行run
方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
//從類路徑下下META‐INF/spring.factories獲取SpringApplicationRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
//回調獲取到的所有SpringApplicationRunListener對象的starting()方法
listeners.starting();
try {
//封裝命令行參數
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//準備環境。創建環境完成後回調SpringApplicationRunListener.environmentPrepared()方法,表示環境已經準備完成
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//打印springboot的圖標
Banner printedBanner = printBanner(environment);
//創建ApplicationContext容器:決定創建的是web的ioc容器還是普通的ioc容器
context = createApplicationContext();
//出現異常以後做異常分析報告的
analyzers = new FailureAnalyzers(context);
//準備上下文環境:將environment保存到ioc容器中;而且執行applyInitializers()方法;
//applyInitializers():回調之前保存的所有的ApplicationContextInitializer的initialize方法;回調所有的//SpringApplicationRunListener的contextPrepared();
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
///prepareContext運行完成以後回調所有的SpringApplicationRunListener的contextLoaded();
//刷新容器:即ioc容器初始化的過程(如果是web應用,還會創建嵌入式的servlet容器)。
//掃描、加載、創建所有組件的地方
refreshContext(context);
//從ioc容器中獲取所有的ApplicationRunner和CommandLineRunner進行回調
//ApplicationRunner先回調,CommandLineRunner再回調
afterRefresh(context, applicationArguments);
//所有的SpringApplicationRunListener回調finished方法
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//整個SpringBoot應用啓動完成以後返回啓動的ioc容器
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
二、springboot應用啓動原理總結
SpringApplication.run(主程序類):
– new SpringApplication(主程序類)
• 判斷是否web應用
• 加載並保存所有ApplicationContextInitializer(META-INF/spring.factories)
• 加載並保存所有ApplicationListener
• 獲取到主程序類
– run()
• 回調所有的SpringApplicationRunListener(META-INF/spring.factories)的starting
• 獲取ApplicationArguments
• 準備環境&回調所有監聽器( SpringApplicationRunListener )
的environmentPrepared
• 打印banner
信息
• 創建ioc容器對象(
–AnnotationConfigEmbeddedWebApplicationContext(web環境容器)
– AnnotationConfigApplicationContext(普通環境容器)
• 準備環境
– 執行ApplicationContextInitializer. initialize()
– 監聽器SpringApplicationRunListener
回調contextPrepared
– 加載主配置類定義信息
– 監聽器SpringApplicationRunListener
回調contextLoaded
• 刷新啓動IOC容器;
– 掃描加載所有容器中的組件
– 包括從META-INF/spring.factories
中獲取的所有EnableAutoConfiguration
組件
• 回調容器中所有的ApplicationRunner
、CommandLineRunner
的run方法
• 監聽器SpringApplicationRunListener回調finished