Spring Boot【原理分析】(1)——SpringApplication
SpringApplication作為Spring Boot的啟動類。
一、入口方法run
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
}
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
例項SpringApplication執行run。
二、初始化函式initialize
SpringApplication構造方法,會呼叫initialize方法進行初始化。
@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
this .webEnvironment = deduceWebEnvironment();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
流程分析:
1.設定配置類
2.推斷是否為WEB環境
3.例項化META-INF/spring.factories檔案中的ApplicationContextInitializer類
4.例項化META-INF/spring.factories檔案中的ApplicationListener類
5.推斷主類
SpringBoot例項化的5個ApplicationContextInitializer(另開一篇寫這5個類)
SpringBoot例項化的9個ApplicationListener(另開一篇寫這9個類)
三、執行方法run
原始碼如下:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
//設定java.awt.headless未配置時預設為true
//是J2SE的一種Headless模式
configureHeadlessProperty();
//例項化SpringApplicationRunListeners
//<1>例項化META-INF/spring.factories檔案中的SpringApplicationRunListener類
SpringApplicationRunListeners listeners = getRunListeners(args);
//這裡看起來是一個啟動,其實根據不同的listener不一樣。
listeners.started();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//<2>建立並重新整理spring上下文
context = createAndRefreshContext(listeners, applicationArguments);
afterRefresh(context, applicationArguments);
// EventPublishingRunListener廣播ApplicationReadyEvent或ApplicationFailedEvent事件
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, ex);
throw new IllegalStateException(ex);
}
}
1.啟動所有SpringApplicationRunListener
SpringBoot例項化的1個SpringApplicationRunListener
EventPublishingRunListener會向SpringApplication的所有ApplicationListener廣播事件。
事件有:ApplicationStartedEvent;ApplicationEnvironmentPreparedEvent;ApplicationPreparedEvent;ApplicationFailedEvent;ApplicationReadyEvent
原始碼中listeners.started();
廣播ApplicationStartedEvent事件。
2.建立並重新整理spring上下文
原始碼如下:
private ConfigurableApplicationContext createAndRefreshContext(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
ConfigurableApplicationContext context;
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
//EventPublishingRunListener廣播ApplicationEnvironmentPreparedEvent
listeners.environmentPrepared(environment);
if (isWebEnvironment(environment) && !this.webEnvironment) {
environment = convertToStandardEnvironment(environment);
}
if (this.bannerMode != Banner.Mode.OFF) {
printBanner(environment);
}
// <2.1>Create, load, refresh and run the ApplicationContext
context = createApplicationContext();
context.setEnvironment(environment);
postProcessApplicationContext(context);
// 初始化所有ApplicationContextInitializer
// 載入BeanFactoryPostProcessor
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
// Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[sources.size()]));
// 對ApplicationContextAware的ApplicationListener設定context
// context新增所有ApplicationListener
// EventPublishingRunListener廣播ApplicationPreparedEvent事件
listeners.contextLoaded(context);
//<2.2> Refresh the context
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
return context;
}
2.1建立context
根據不同的environment會建立不同的ApplicationContext。
Web:AnnotationConfigEmbeddedWebApplicationContext
Standard:AnnotationConfigApplicationContext
2.2重新整理上下文
重點後面另開一篇