目錄
1、創建Environment對象(getOrCreateEnvironment)
2、配置Environment(ConversionService、main方法傳入的args參數、Profile)
3、SpringApplicationRunListener的environmentPrepared回調
2、爲ConfigurableApplicationContext設置屬性
3、回調ApplicationContextInitializer的initialize方法
4、回調SpringApplicationRunListener的contextPrepared方法
5、將applicationArguments、Banner註冊成單例Bean
6、是否添加LazyInitializationBeanFactoryPostProcessor進行懶加載處理
8、回調SpringApplicationRunListener的contextLoaded方法
// 將main方法的args參數進行封裝
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 準備Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 配置忽略注入的Bean
configureIgnoreBeanInfo(environment);
// 打印banner圖
Banner printedBanner = printBanner(environment);
// 反射創建ApplicationContext對象
context = createApplicationContext();
// 還在加載自動裝配的SpringBootExceptionReporter類型, 默認只有FailureAnalyzers
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 爲ApplicationContext設置屬性、做refresh的準備工作
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
一、創建和配置Environment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
1、創建Environment對象(getOrCreateEnvironment)
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
根據之前斷定的webApplicationType類型(run之前可以通過set方法進行修改),創建不同類型的Environment類型。
2、配置Environment(ConversionService、main方法傳入的args參數、Profile)
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
3、SpringApplicationRunListener的environmentPrepared回調
void environmentPrepared(ConfigurableEnvironment environment) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.environmentPrepared(environment);
}
}
4、自定義Environment
如果是自定義Environment,則使用EnvironmentConverter進行處理。
二、反射創建ApplicationContext對象
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET: // AnnotationConfigServletWebServerApplicationContext
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE: // AnnotationConfigReactiveWebServerApplicationContext
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default: // AnnotationConfigApplicationContext
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) { // 省略部分代碼 }
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
與配置ConfigurableEnvironment 一樣,根據webApplicationType通過反射創建ConfigurableApplicationContext 類型對象。
三、prepareContext
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 爲Spring容器設置初始化的環境
context.setEnvironment(environment);
// 爲ConfigurableApplicationContext設置屬性(bean名稱生成器、Resource加載器和
// ConversionService)
postProcessApplicationContext(context);
// 回調ApplicationContextInitializer的initialize方法
applyInitializers(context);
// 回調SpringApplicationRunListener的contextPrepared方法
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 將applicationArguments、Banner註冊成單例Bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 是否添加LazyInitializationBeanFactoryPostProcessor進行懶加載處理
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// 將sources註冊BeanDefinition,沒有特殊添加,則會將main註冊BeanDefinition
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
// 回調SpringApplicationRunListener的contextLoaded方法
listeners.contextLoaded(context);
}
1、爲Spring容器設置初始化的環境
context.setEnvironment(environment);
2、爲ConfigurableApplicationContext設置屬性
默認bean名稱生成器、Resource加載器爲空,則不會進行設置。ConversionService則會設置ApplicationConversionService.sharedInstance單例對象。
3、回調ApplicationContextInitializer的initialize方法
循環調用ApplicationContextInitializer的initialize初始化方法。
4、回調SpringApplicationRunListener的contextPrepared方法
5、將applicationArguments、Banner註冊成單例Bean
其Bean名稱和Bean對象對應關係爲(後續我們需要的時候可以通過getBean方法進行獲取,使用):
|
|
|
|
6、是否添加LazyInitializationBeanFactoryPostProcessor進行懶加載處理
7、 將main類註冊BeanDefinition
將sources註冊BeanDefinition,沒有特殊添加,則會將main註冊BeanDefinition。個人理解,上面將不會再進行修改的applicationArguments等直接註冊成Bean。而將可能通過BeanPostProcessor修改的main方法類,只是註冊成BeanDefinition。
8、回調SpringApplicationRunListener的contextLoaded方法