SpringBoot启动流程分析
目录
- SpringBoot启动流程分析
-
- 1.SpringApplicationRunListeners
- 2.初始化Environment对象
- 3 创建applicationContext
-
- 3.1 createApplicationContext
- 3.2 prepareContext
- 3.3 refreshContext(AbstractApplicationContext#refresh)
-
- 3.3.1 prepareRefresh
- 3.3.2 obtainFreshBeanFactory
- 3.3.3 prepareBeanFactory
-
- 3.3.3.1 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
- 3.3.3.2 beanFactory.ignoreDependencyInterface(xxx.class);
- 3.3.3.3 registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue);
- 3.3.3.4 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
- 3.3.4 postProcessBeanFactory
- 3.3.5 invokeBeanFactoryPostProcessors
- 3.3.5 registerBeanPostProcessors
- 3.3.6 initApplicationEventMulticaster
- 3.3.7 registerListeners
- 3.3.8 finishBeanFactoryInitialization
1.SpringApplicationRunListeners
构造SpringApplicationRunListeners,其中包含多个SpringApplicationRunListener
SpringApplicationRunListener实例化过程:
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] {
SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 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;
}
通过SpringFactoriesLoader获取到spring.factories中定义的SpringApplicationRunListener
默认情况下只有EventPublishingRunListener,会在spring启动的不同阶段发布不同的事件
构造完成后调用listeners.starting(),触发所有listener中的starting方法
2.初始化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;
}
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类型创建不同的ConfigurableEnvironment
这里以最常见的SERVLET举例
构造方法内部通过调用customizePropertySources方法对propertySources进行初始化和赋值
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
}
super.customizePropertySources(propertySources);
}
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
方法结束后一共初始化了4个属性
- servletConfigInitParams
- servletContextInitParams
- systemProperties
- systemEnvironment
configureEnvironment
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
- 配置类型转化服务ApplicationConversionService
- 通过configurePropertySources新增defaultProperties和addCommandLineProperties
- 配置profile
ConfigurationPropertySources.attach
public static void attach(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
if (attached != null && attached.getSource() != sources) {
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
attached = null;
}
if (attached == null) {
sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
new SpringConfigurationPropertySources(sources)));
}
}
把所有的属性又包了一层,作为configurationProperties
listeners.environmentPrepared(environment);
触发监听器environmentPrepared事件
将 environment中的spring.main开头的属性 绑定到SpringApplication 中的属性值上
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
try {
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
configureIgnoreBeanInfo(environment);
设置spring.beaninfo.ignore的值,默认为true,保证某些bean不会添加到准备环境中
3 创建applicationContext
3.1 createApplicationContext
根据不同的webApplicationType初始化ApplicationContext
以servlet为例,则是创建出AnnotationConfigServletWebApplicationContext对象
还创建了reader对象、scanner对象和新的environment对象
3.2 prepareContext
初始化applicationContext,将application注册beanDefinition,为refresh做准备
3.2.1 postProcessApplicationContext
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if