SpringApplication.run(BeautyApplication.class, args);
複製代碼
執行此方法來加載整個SpringBoot的環境。java
SpringApplication.java
web
/** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @return a running {@link ApplicationContext} */
public ConfigurableApplicationContext run(String... args) {
//...
}
複製代碼
調用SpringApplication.java
中的 run 方法,目的是加載Spring Application
,同時返回 ApplicationContext
。spring
記錄整個
Spring Application
的加載時間!併發
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// ...
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
複製代碼
// 聲明 ApplicationContext
ConfigurableApplicationContext context = null;
// 聲明 一個異常報告集合
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
複製代碼
指定
java.awt.headless
,默認是true
通常是在程序開始激活headless模式,告訴程序,如今你要工做在Headless mode下,就不要期望硬件幫忙了,你得自力更生,依靠系統的計算能力模擬出這些特性來。app
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(
SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
複製代碼
SpringApplicationRunListener
負責加載ApplicationListener
事件。less
SpringApplicationRunListeners listeners = getRunListeners(args);
// 開始
listeners.starting();
// 處理全部 property sources 配置和 profiles 配置,準備環境,分爲標準 Servlet 環境和標準環境
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
// 準備應用上下文
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
// 完成
listeners.started(context);
// 異常
handleRunFailure(context, ex, exceptionReporters, listeners);
// 執行
listeners.running(context);
複製代碼
getRunListeners
中根據type = SpringApplicationRunListener.class
去拿到了全部的Listener
並根據優先級排序。 對應的就是META-INF/spring.factories
文件中的org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener
this
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// 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;
}
複製代碼
在
ApplicationListener
中 , 能夠針對任何一個階段插入處理代碼
。spa
public interface SpringApplicationRunListener {
/** * Called immediately when the run method has first started. Can be used for very * early initialization. */
void starting();
/** * Called once the environment has been prepared, but before the * {@link ApplicationContext} has been created. * @param environment the environment */
void environmentPrepared(ConfigurableEnvironment environment);
/** * Called once the {@link ApplicationContext} has been created and prepared, but * before sources have been loaded. * @param context the application context */
void contextPrepared(ConfigurableApplicationContext context);
/** * Called once the application context has been loaded but before it has been * refreshed. * @param context the application context */
void contextLoaded(ConfigurableApplicationContext context);
/** * The context has been refreshed and the application has started but * {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner * ApplicationRunners} have not been called. * @param context the application context. * @since 2.0.0 */
void started(ConfigurableApplicationContext context);
/** * Called immediately before the run method finishes, when the application context has * been refreshed and all {@link CommandLineRunner CommandLineRunners} and * {@link ApplicationRunner ApplicationRunners} have been called. * @param context the application context. * @since 2.0.0 */
void running(ConfigurableApplicationContext context);
/** * Called when a failure occurs when running the application. * @param context the application context or {@code null} if a failure occurred before * the context was created * @param exception the failure * @since 2.0.0 */
void failed(ConfigurableApplicationContext context, Throwable exception);
}
複製代碼
在加載Spring Application以前執行,全部資源和環境未被加載。日誌
建立
ConfigurableEnvironment
; 將配置的環境綁定到Spring Application
中;code
private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (this.webApplicationType == WebApplicationType.NONE) {
environment = new EnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
複製代碼
配置忽略的Bean;
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
if (System.getProperty(
CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
Boolean ignore = environment.getProperty("spring.beaninfo.ignore",
Boolean.class, Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
ignore.toString());
}
}
複製代碼
打印日誌-加載的資源
Banner printedBanner = printBanner(environment);
複製代碼
根據不一樣的
WebApplicationType
建立Context
context = createApplicationContext();
複製代碼
支持定製刷新
/** * Register a shutdown hook with the JVM runtime, closing this context * on JVM shutdown unless it has already been closed at that time. * <p>This method can be called multiple times. Only one shutdown hook * (at max) will be registered for each context instance. * @see java.lang.Runtime#addShutdownHook * @see #close() */
void registerShutdownHook();
複製代碼
刷新後的實現方法暫未實現
/** * Called after the context has been refreshed. * @param context the application context * @param args the application arguments */
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}
複製代碼
到此爲止,
Spring Application
的環境和資源都加載完畢了; 發佈應用上下文啓動完成事件; 執行全部 Runner 運行器 - 執行全部 ApplicationRunner 和 CommandLineRunner 這兩種運行器
// 啓動
callRunners(context, applicationArguments);
複製代碼
觸發全部 SpringApplicationRunListener 監聽器的 running 事件方法