前一文学习了项目启动的流程:
(一)new SpringApplication
- 配置source和web环境;
- 创建初始化构造器和应用监听器;
- 配置应用的主方法所在类;
(二)run 第一部分
- 初始化计时、启动上下文、设置系统参数;
- 初始化监听器列表;
- 发布springboot开始启动事件(从applicationListeners中过滤出4个能监听ApplicationStartingEvent事件的,并启动它们)
继续下面的学习这个方法:
public ConfigurableApplicationContext run(String... args) {
//1、StopWatch简单的看成一个stop watch的机制,保存stop的记录信息。
//初始化一个计时器,并开始计时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//初始化启动上下文
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
//2、configureHeadlessProperty即配置headless模式,这种模式是一种系统缺少显示设备、键盘和鼠标外设的情况模式。
this.configureHeadlessProperty();
//3、SpringApplicationListeners为SpringApplicationRunListener接口实现集合(创建SpringApplicationRunListener初始化构造器)初始化监听器列表
//可以理解这个接口就是在spring启动整个过程都需要回调这些listener
//debug能发现,拿到了一个名为EventPublishingRunListener(RunListener构造方法中关联上了全部applicationListener),这个就是用来进行触发publishEvent的被观察者
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//启动EventPublishingRunListener,从而过滤并启动相关Listener
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//4、ConfigurableEnvironment为配置环境对象,简单理解所有的配置信息汇总在这个对象中
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
this.configureIgnoreBeanInfo(environment);
//5、Banner就是我们常在控制台输出的画面横幅,可以使用图片或者文本进行替换
Banner printedBanner = this.printBanner(environment);
//6、ConfigurableApplicationContext根据webApp…Type进行构造的上下文对象
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//7、接下来进入关键步骤的第一步:prepareContext,准备容器阶段,将执行所有的initializers逻辑,做初始化准备操作。
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//8、refreshContext,可以理解成容器初始化节点,将执行bean的创建和实例化。
this.refreshContext(context);
//9、afterRefresh,容器后处理, 可以看到会找到ApplicationRunner和CommandLineRunner的实现类并执行。但从2.x版本来看,似乎这个方法是个空方法,applicationRun和commandRun移到启动最后。
this.afterRefresh(context, applicationArguments);
//10、然后根据stopwatch打印出启动时间
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
//11、这里调用ApplicationRunner和CommandLineRunner的实现类
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
回到正题,继续run方法的第二部分try部分:(当前以最新SpringbootV2.4.4版本进行学习)
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//4、ConfigurableEnvironment为配置环境对象,简单理解所有的配置信息汇总在这个对象中
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
this.configureIgnoreBeanInfo(environment);
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
args参数在启动程序时是可配置的,不配置为null,下面跟进一下方法(将深入方法揉到一起)简单命令行解析器解析参数,最后以PropertySource对象形式赋值给source。DefaultApplicationArguments就是保存了两种形式的参数值
public DefaultApplicationArguments(String... args) {
Assert.notNull(args, "Args must not be null");
this.source = new DefaultApplicationArguments.Source(args);
this.args = args;
}
/**
*跟进source构造方法
**/
private static class Source extends SimpleCommandLinePropertySource {
Source(String[] args) {
super(args);
}
... ...
}
/**
*跟进父类构造方法,将处理结果赋值给父类,即PropertySource对象
**/
public class SimpleCommandLinePropertySource extends CommandLinePropertySource<CommandLineArgs> {
public SimpleCommandLinePropertySource(String... args) {
super((new SimpleCommandLineArgsParser()).parse(args));
}
... ...
}
/**
*跟进parse方法(命令行解析器,将启动参数字符串截取出key与value)
**/
public CommandLineArgs parse(String... args) {
CommandLineArgs commandLineArgs = new CommandLineArgs();
String[] var3 = args;
int var4 = args.length;
for(int var5 = 0; var5 < var4; ++var5) {
String arg = var3[var5];
if (arg.startsWith("--")) {
String optionText = arg.substring(2);
String optionValue = null;
int indexOfEqualsSign = optionText.indexOf(61);
String optionName;
if (indexOfEqualsSign > -1) {
optionName = optionText.substring(0, indexOfEqualsSign);
optionValue = optionText.substring(indexOfEqualsSign + 1);
} else {
optionName = optionText;
}
if (optionName.isEmpty()) {
throw new IllegalArgumentException("Invalid argument syntax: " + arg);
}
commandLineArgs.addOptionArg(optionName, optionValue);
} else {
commandLineArgs.addNonOptionArg(arg);
}
}
return commandLineArgs;
}
下面执行 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);逐行来看
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
====> ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
} else {
switch(this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
}
public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
public static final String SERVLET_CONTEXT_PROPERTY_SOURCE_NAME = "servletContextInitParams";
public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties";
public StandardServletEnvironment() {
}
protected StandardServletEnvironment(MutablePropertySources propertySources) {
super(propertySources);
}
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new StubPropertySource("servletConfigInitParams"));
propertySources.addLast(new StubPropertySource("servletContextInitParams"));
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
propertySources.addLast(new JndiPropertySource("jndiProperties"));
}
super.customizePropertySources(propertySources);
}
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
}
}
/**
*调用父类customizeProperty方法
**/
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new PropertiesPropertySource("systemProperties", this.getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", this.getSystemEnvironment()));
}
下面来看下propertySources对象是怎么保存的,原来是用list保存了PropertySource对象(StandardEnvironment的customizePropertiesSources中加入systemEnvironment和systemProperties,StandardServletEnvironment的customizePropertiesSources中加入servletContextInitParams和servletConfigInitParams)
public class MutablePropertySources implements PropertySources {
private final List<PropertySource<?>> propertySourceList;
public MutablePropertySources() {
this.propertySourceList = new CopyOnWriteArrayList();
}
... ...
}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
====> this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
//ConversionService在前面Listener有执行过初始化(上一章节),此时为true加载到容器中
//包含一些基本类型的转换等,都放到environment中
if (this.addConversionService) {
// 加载一些转换器和格式化器,下面跟进代码
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService)conversionService);
}
//配置属性(defaultProperties和commandLineProperties两部分)
this.configurePropertySources(environment, args);
//内容空,之前版本是加载spring.profile.active配置的(应该是版本导致不在这里处理了)
this.configureProfiles(environment, args);
}
public static ConversionService getSharedInstance() {
ApplicationConversionService sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
Class var1 = ApplicationConversionService.class;
synchronized(ApplicationConversionService.class) {
sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
sharedInstance = new ApplicationConversionService();
ApplicationConversionService.sharedInstance = sharedInstance;
}
}
}
return sharedInstance;
}
public ApplicationConversionService(){
... ...
configure(this);
}
public static void configure(FormatterRegistry registry) {
DefaultConversionService.addDefaultConverters(registry);
DefaultFormattingConversionService.addDefaultFormatters(registry);
addApplicationFormatters(registry);
addApplicationConverters(registry);
}
public static void addApplicationConverters(ConverterRegistry registry) {
addDelimitedStringConverters(registry);
registry.addConverter(new StringToDurationConverter());
registry.addConverter(new DurationToStringConverter());
registry.addConverter(new NumberToDurationConverter());
registry.addConverter(new DurationToNumberConverter());
registry.addConverter(new StringToPeriodConverter());
registry.addConverter(new PeriodToStringConverter());
registry.addConverter(new NumberToPeriodConverter());
registry.addConverter(new StringToDataSizeConverter());
registry.addConverter(new NumberToDataSizeConverter());
registry.addConverter(new StringToFileConverter());
registry.addConverter(new InputStreamSourceToByteArrayConverter());
registry.addConverterFactory(new LenientStringToEnumConverterFactory());
registry.addConverterFactory(new LenientBooleanToEnumConverterFactory());
if (registry instanceof ConversionService) {
addApplicationConverters(registry, (ConversionService)registry);
}
}
private static void addApplicationConverters(ConverterRegistry registry, ConversionService conversionService) {
registry.addConverter(new CharSequenceToObjectConverter(conversionService));
}
public static void addDelimitedStringConverters(ConverterRegistry registry) {
ConversionService service = (ConversionService)registry;
registry.addConverter(new ArrayToDelimitedStringConverter(service));
registry.addConverter(new CollectionToDelimitedStringConverter(service));
registry.addConverter(new DelimitedStringToArrayConverter(service));
registry.addConverter(new DelimitedStringToCollectionConverter(service));
}
public static void addApplicationFormatters(FormatterRegistry registry) {
registry.addFormatter(new CharArrayFormatter());
registry.addFormatter(new InetAddressFormatter());
registry.addFormatter(new IsoOffsetFormatter());
}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
====> ConfigurationPropertySources.attach((Environment)environment);
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
//检查environment中propertySource中没有configurationProperties,并添加configurationProperties
//如果有configurationProperties,删除后重新添加configurationProperties
public static void attach(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
MutablePropertySources sources = ((ConfigurableEnvironment)environment).getPropertySources();
PropertySource<?> attached = sources.get("configurationProperties");
if (attached != null && attached.getSource() != sources) {
sources.remove("configurationProperties");
attached = null;
}
if (attached == null) {
sources.addFirst(new ConfigurationPropertySourcesPropertySource("configurationProperties", new SpringConfigurationPropertySources(sources)));
}
}
debug发现environment中已经包含了5个propertySource
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
====> listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
this.doWithListeners("spring.boot.application.environment-prepared", (listener) -> {
listener.environmentPrepared(bootstrapContext, environment);
});
}
此处listener还是前文提到的runListener,此处和前文过滤并执行Listener逻辑相似。下面看EventPublishingRunListener中environmentPrepared方法
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
}
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
Executor executor = this.getTaskExecutor();
Iterator var5 = this.getApplicationListeners(event, type).iterator();
while(var5.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var5.next();
if (executor != null) {
executor.execute(() -> {
this.invokeListener(listener, event);
});
} else {
this.invokeListener(listener, event);
}
}
}
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = source != null ? source.getClass() : null;
AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
AbstractApplicationEventMulticaster.CachedListenerRetriever newRetriever = null;
AbstractApplicationEventMulticaster.CachedListenerRetriever existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.get(cacheKey);
if (existingRetriever == null && (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
newRetriever = new AbstractApplicationEventMulticaster.CachedListenerRetriever();
existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
if (existingRetriever != null) {
newRetriever = null;
}
}
if (existingRetriever != null) {
Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
if (result != null) {
return result;
}
}
return this.retrieveApplicationListeners(eventType, sourceType, newRetriever);
}
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList();
Set<ApplicationListener<?>> filteredListeners = retriever != null ? new LinkedHashSet() : null;
Set<String> filteredListenerBeans = retriever != null ? new LinkedHashSet() : null;
LinkedHashSet listeners;
LinkedHashSet listenerBeans;
synchronized(this.defaultRetriever) {
listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
}
Iterator var9 = listeners.iterator();
while(var9.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var9.next();
if (this.supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
filteredListeners.add(listener);
}
allListeners.add(listener);
}
}
if (!listenerBeans.isEmpty()) {
ConfigurableBeanFactory beanFactory = this.getBeanFactory();
Iterator var16 = listenerBeans.iterator();
while(var16.hasNext()) {
String listenerBeanName = (String)var16.next();
try {
if (this.supportsEvent(beanFactory, listenerBeanName, eventType)) {
ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
if (beanFactory.isSingleton(listenerBeanName)) {
filteredListeners.add(listener);
} else {
filteredListenerBeans.add(listenerBeanName);
}
}
allListeners.add(listener);
}
} else {
Object listener = beanFactory.getSingleton(listenerBeanName);
if (retriever != null) {
filteredListeners.remove(listener);
}
allListeners.remove(listener);
}
} catch (NoSuchBeanDefinitionException var13) {
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null) {
if (filteredListenerBeans.isEmpty()) {
retriever.applicationListeners = new LinkedHashSet(allListeners);
retriever.applicationListenerBeans = filteredListenerBeans;
} else {
retriever.applicationListeners = filteredListeners;
retriever.applicationListenerBeans = filteredListenerBeans;
}
}
return allListeners;
}
最后得到事件监听器有6个,并开始执行invokeListener方法(即执行listener监听事件方法onApplicationEvent)
// 看一下EnvironmentPostProcessorApplicationListener
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
this.onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent)event);
}
if (event instanceof ApplicationPreparedEvent) {
this.onApplicationPreparedEvent((ApplicationPreparedEvent)event);
}
if (event instanceof ApplicationFailedEvent) {
this.onApplicationFailedEvent((ApplicationFailedEvent)event);
}
}
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
SpringApplication application = event.getSpringApplication();
// getEnvironmentPostProcessors返回全部环境后置处理器(spring.factories中获取)
Iterator var4 = this.getEnvironmentPostProcessors(event.getBootstrapContext()).iterator();
while(var4.hasNext()) {
EnvironmentPostProcessor postProcessor = (EnvironmentPostProcessor)var4.next();
postProcessor.postProcessEnvironment(environment, application);
}
}
debug发现EnvironmentPostProcessorApplicationListener中ConfigDataEnvironmentPostProcessor就将spring.profile.active值配置给了参数environment.activeProfiles,方便后续加载activeProfiles里的内容。刚刚未做任何处理的空方法this.configureProfiles(environment, args),在新版中方法内容迁移到了后置处理器中去处理了。也在这里更新了propertyList[8个值]。其他监听器及后置处理器不再赘述。
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
====> DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
public static void moveToEnd(ConfigurableEnvironment environment) {
moveToEnd(environment.getPropertySources());
}
// 去除environment.propertySources[list|5个值]中defaultProperties
public static void moveToEnd(MutablePropertySources propertySources) {
PropertySource<?> propertySource = propertySources.remove("defaultProperties");
if (propertySource != null) {
propertySources.addLast(propertySource);
}
}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
====> this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
这里检查additionalProfiles是否已经加载过了profiles,前面已经加载了,继续向下执行,将环境绑定到application中,环境变量类型校验与转换,最后经转换后防止丢配置进行环境对象刷新(重置environment.propertySource[list0]的configurationProperties)
进入run方法的主流程 this.configureIgnoreBeanInfo(environment);
配置忽略某些bean,配置后可以debug到下图
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
if (System.getProperty("spring.beaninfo.ignore") == null) {
Boolean ignore = (Boolean)environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
System.setProperty("spring.beaninfo.ignore", ignore.toString());
}
}
进入run方法的主流程 Banner printedBanner = this.printBanner(environment);
private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Mode.OFF) { return null; } else { ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader((ClassLoader)null); SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter((ResourceLoader)resourceLoader, this.banner); return this.bannerMode == Mode.LOG ? bannerPrinter.print(environment, this.mainApplicationClass, logger) : bannerPrinter.print(environment, this.mainApplicationClass, System.out); } }
汇总一下:
(一)new SpringApplication
- 配置source和web环境;
- 创建初始化构造器和应用监听器;
- 配置应用的主方法所在类;
(二)run 第一二部分
- 初始化计时stopWatch、启动上下文bootstrapContext、设置系统参数headless;
- 初始化监听器列表SpringApplicationRunListeners;
- 发布springboot开始启动事件(从applicationListeners中过滤出4个能监听ApplicationStartingEvent事件的,并启动它们)
- 装配命令行参数applicationArguments(对象中装载4个propertySource);
- 准备应用程序运行的环境ConfigurableEnvironment(从applicationListeners中过滤出6个能监听ApplicationEnvironmentPreparedEvent事件的,并启动它们。监听器中关联启动了一些后置处理器处理数据,最终目的是为应用环境做准备)
- 配置忽略bean和打印banner
----红色部分为本节内容----