一般在Spring Boot应用的主方法中,都会调用SpringApplication类中的run方法来启动框架。而该方法则是Spring Boot的运行流程这条主线的入口,本文将会以此方法为起点,来完整分析Spring Boot的运行流程。
本文分析的Spring Boot源码版本是2.7.x,Spring Framework的源码版本是5.3.22。本文涉及的源码中存在大量与Spring Framework交互的情况,为了提高阅读体验,这里仅仅展示Spring Boot相关的源码,尽量不过多涉及Spring Framework源码。
run方法
SpringApplication中共有3个run方法,其中一个实例方法,两个静态方法。在静态的run方法中,也是先创建SpringApplication对象(参考Spring Boot的构造流程),然后调用实例run方法。
静态run方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
真正的重点在实例run方法中。
实例run方法
private boolean logStartupInfo = true;
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
/**
* 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) {
long startTime = System.nanoTime();
// 创建启动上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
// 该变量记录Spring中的应用上下文
ConfigurableApplicationContext context = null;
// 配置headless属性
configureHeadlessProperty();
// 获取SpringApplicationRunLister数组并封装成SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
/*
* 启动listener,内部会遍历各个SpringApplicationRunLister,
* 对于默认的EventPublishingRunListener而言,内部会通过事件广播器向各个ApplicationListener广播starting事件。
*/
listeners.starting(bootstrapContext, this.mainApplicationClass);
/*
* 这里简要对事件处理做一个总结(以starting事件为例,其他类型事件相似):
* SpringApplicationRunListeners.starting ->
* 遍历SpringApplicationRunListener,依次调用每个listener的starting方法 ->
* EventPublishingRunListener.starting ->
* initialMulticaster.multicastEvent(ApplicationStartingEvent) 或者 context.publishEvent
*
* EventPublishingRunListener内部针对不同的事件处理的方式有区别,有些是通过initialMulticaster.multicastEvent处理的,
* 另外有些是通过context.publishEvent来处理的,这是为什么?
* contextLoad事件是不同事件广播方式的分水岭,因为该事件发生时,context才算初始化完成,之后才能利用context.publishEvent来发布事件。
*
*/
try {
// 创建应用参数对象
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 加载属性配置
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 配置spring.beaninfo.ignore属性
configureIgnoreBeanInfo(environment);
// 打印banner (此功能华而不实,跳过)
Banner printedBanner = printBanner(environment);
// 创建应用上下文
context = createApplicationContext();
// 设置应用上下文的startup,应用上下文本身的启动也有很多阶段,所以可以用该startup来记录
context.setApplicationStartup(this.applicationStartup);
// 准备应用上下文和属性对象之间的关联
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 初始化(刷新)应用上下文, 这里最终调用的是特别熟悉且重要和复杂的AbstractApplicationContext#refresh()方法
refreshContext(context);
// 执行应用上下文刷新之后的操作,默认是空操作
afterRefresh(context, applicationArguments);
// 计算启动耗时
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
// 打印启动耗时到日志中
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 通知listener,应用上下文启动完毕
listeners.started(context, timeTakenToStartup);
// 调用runner
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
// 处理异常
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 计算应用上下文准备时间
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// 通知listener,应用上下文准备完毕
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
// 异常处理
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 返回应用上下文对象
return context;
}
这个方法的涉及的内容稍微有点多,大致可以总结为下面的流程:
- 创建启动上下文;
- 配置headless属性;
- 获取SpringApplicationRunListener;
- 发起starting事件;
- 准备environment;
- 发起environmentPrepared事件;
- 创建应用上下文;
- 刷新应用上下文;
- 发起started事件;
- 调用runner;
下面依次对上面几个步骤进行展开分析。
启动上下文
private DefaultBootstrapContext createBootstrapContext() {
// 直接创建默认启动上下文实例
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
// 通过构造流程中创建的初始化器对上下文实例进行初始化,默认情况下bootstrapRegistryInitializers列表的长度为0
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
在Spring Boot的默认情况下,没有自动配置BootstrapRegistryInitializer,但在Spring Cloud中会使用,具体细节在相应文章中进行分析。
headless属性
在Linux服务器使用Spring Boot进行图形化操作的时候,会遇到性能问题。原因在于Java图形化工具包AWT在某些情况下会使用图形化界面操作,而Linux服务器一般没有图形化支持,因此会导致处理速度非常慢。 所以可以通过设置系统参数java.awt.headless为true来禁用AWT的图形界面。
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
private boolean headless = true;
private void configureHeadlessProperty() {
// 这里其实是在设置`java.awt.headless`属性的默认值, this.headless默认值是true。
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
SpringApplicationRunListener
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
private SpringApplicationRunListeners getRunListeners(String[] args) {
// 实例化SpringApplicationRunListener子类的时查找对应构造器的参数类型
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
/*
* 从spring.factories文件中加载SpringApplicationRunListener相关配置,并实例化这些配置类的对象,
* 然后作为参数(第二个参数)构造SpringApplicationRunListeners
* 默认仅提供了一个,即EventPublishingRunListener, 参考文件spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories
*/
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
Spring Boot会从spring.factories文件中加载SpringApplicationRunListener配置的类型并实例化,默认情况下就只配置了一个:EventPublishingRunListener。然后将其封装为SpringApplicationRunListeners。 ApplicationStartup用于标记应用启动的阶段,在这里使用到了ApplicationStartup.DEFAULT,默认的是空实现,即其实现的StartupStep不做什么操作。
/**
* Instruments the application startup phase using {@link StartupStep steps}.
* <p>The core container and its infrastructure components can use the {@code ApplicationStartup}
* to mark steps during the application startup and collect data about the execution context
* or their processing time.
*
* @author Brian Clozel
* @since 5.3
*/
public interface ApplicationStartup {
/**
* Default "no op" {@code ApplicationStartup} implementation.
* <p>This variant is designed for minimal overhead and does not record data.
*/
ApplicationStartup DEFAULT = new DefaultApplicationStartup();
/**
* Create a new step and marks its beginning.
* <p>A step name describes the current action or phase. This technical
* name should be "." namespaced and can be reused to describe other instances of
* the same step during application startup.
* @param name the step name
*/
StartupStep start(String name);
}
/**
* Default "no op" {@code ApplicationStartup} implementation.
*
* <p>This variant is designed for minimal overhead and does not record events.
*
* @author Brian Clozel
*/
class DefaultApplicationStartup implements ApplicationStartup {
private static final DefaultStartupStep DEFAULT_STARTUP_STEP = new DefaultStartupStep();
@Override
public DefaultStartupStep start(String name) {
return DEFAULT_STARTUP_STEP;
}
static class DefaultStartupStep implements StartupStep {
private final DefaultTags TAGS = new DefaultTags();
@Override
public String getName() {
return "default";
}
@Override
public long getId() {
return 0L;
}
@Override
public Long getParentId() {
return null;
}
@Override
public Tags getTags() {
return this.TAGS;
}
@Override
public StartupStep tag(String key, String value) {
return this;
}
@Override
public StartupStep tag(String key, Supplier<String> value) {
return this;
}
@Override
public void end() {
}
static class DefaultTags implements StartupStep.Tags {
@Override
public Iterator<StartupStep.Tag> iterator() {
return Collections.emptyIterator();
}
}
}
}
SpringApplicationRunListeners
SpringApplicationRunListeners中定义了很多事件方法,可以通过这些方法来发起事件。这些方法都是在遍历所封装的SpringApplicationRunListener,然后通过listener来执行操作。
class SpringApplicationRunListeners {
private final Log log;
private final List<SpringApplicationRunListener> listeners;
private final ApplicationStartup applicationStartup;
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners,
ApplicationStartup applicationStartup) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
this.applicationStartup = applicationStartup;
}
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
// 调用每一个listener的starting方法
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
doWithListeners("spring.boot.application.environment-prepared",
(listener) -> listener.environmentPrepared(bootstrapContext, environment));
}
void contextPrepared(ConfigurableApplicationContext context) {
doWithListeners("spring.boot.application.context-prepared", (listener) -> listener.contextPrepared(context));
}
void contextLoaded(ConfigurableApplicationContext context) {
doWithListeners("spring.boot.application.context-loaded", (listener) -> listener.contextLoaded(context));
}
void started(ConfigurableApplicationContext context, Duration timeTaken) {
doWithListeners("spring.boot.application.started", (listener) -> listener.started(context, timeTaken));
}
void ready(ConfigurableApplicationContext context, Duration timeTaken) {
doWithListeners("spring.boot.application.ready", (listener) -> listener.ready(context, timeTaken));
}
void failed(ConfigurableApplicationContext context, Throwable exception) {
doWithListeners("spring.boot.application.failed",
(listener) -> callFailedListener(listener, context, exception), (step) -> {
step.tag("exception", exception.getClass().toString());
step.tag("message", exception.getMessage());
});
}
private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
Throwable exception) {
try {
listener.failed(context, exception);
}
catch (Throwable ex) {
if (exception == null) {
ReflectionUtils.rethrowRuntimeException(ex);
}
if (this.log.isDebugEnabled()) {
this.log.error("Error handling failed", ex);
}
else {
String message = ex.getMessage();
message = (message != null) ? message : "no error message";
this.log.warn("Error handling failed (" + message + ")");
}
}
}
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction) {
doWithListeners(stepName, listenerAction, null);
}
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
Consumer<StartupStep> stepAction) {
/*
* 创建表示启动步骤的对象
* 这里的this.applicationStartup默认情况下是DefaultApplicationStartup,start后创建的是DefaultStartupStep对象,
* 而DefaultStartupStep的tag和end都是空操作,即什么都不做。
*/
StartupStep step = this.applicationStartup.start(stepName);
// 执行listener操作
this.listeners.forEach(listenerAction);
// 执行step操作
if (stepAction != null) {
stepAction.accept(step);
}
// 结束当前启动步骤
step.end();
}
}
EventPublishingRunListener
在其构造方法中,创建了事件广播器,并往里面添加了事件监听器。这里的事件监听器就是在SpringApplication构造过程中创建的。
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
// 创建事件广播器
this.initialMulticaster = new SimpleApplicationEventMulticaster();
/*
* 这里的ApplicationListener是在构建SpringApplication的时候根据spring.factories中的配置来创建的;
* 而EventPublishingRunListener(作为SpringApplicationRunListener的子类)则是在SpringApplication的run方法执行的时候根据
* spring.factories中的配置来创建的,别搞混了这两种listener
*/
for (ApplicationListener<?> listener : application.getListeners()) {
// 往事件广播器中注册事件监听器,便于后续将事件发送到事件监听器
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public int getOrder() {
return 0;
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
// 广播starting事件
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
// 广播environmentPrepared事件
this.initialMulticaster.multicastEvent(
new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
// 广播applicationContextInitialized事件
this.initialMulticaster
.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
// 广播applicationPrepared事件
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context, timeTaken));
// 发布applicationStarted事件
AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken));
// 发布applicationReady事件
AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
if (context != null && context.isActive()) {
// Listeners have been registered to the application context so we should
// use it at this point if we can
context.publishEvent(event);
}
else {
// An inactive context may not have a multicaster so we use our multicaster to
// call all of the context's listeners instead
if (context instanceof AbstractApplicationContext) {
for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
.getApplicationListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
this.initialMulticaster.multicastEvent(event);
}
}
private static class LoggingErrorHandler implements ErrorHandler {
private static final Log logger = LogFactory.getLog(EventPublishingRunListener.class);
@Override
public void handleError(Throwable throwable) {
logger.warn("Error calling ApplicationEventListener", throwable);
}
}
}
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
在这些事件方法中,都是先创建事件对象ApplicationEvent,然后交由SimpleApplicationEventMulticaster进行广播。 SimpleApplicationEventMulticaster是Spring Framework提供的类,内部实现很简单,就是调用各个ApplicationListener的onApplicationEvent方法,这里就不贴代码了。
Environment
在prepareEnvironment方法中处理Spring Boot应用的Environment对象。
private boolean isCustomEnvironment = false;
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
// 获取或创建environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 注意,这里调用的getSourceArgs()并不是返回内部的source属性(已解析参数),而是args(未解析参数)
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 如果environment中不存在名为configurationProperties的属性源,则创建新的对象并将其放在属性源列表中的第一个
ConfigurationPropertySources.attach(environment);
// 广播environmentPrepared事件
listeners.environmentPrepared(bootstrapContext, environment);
// 将默认属性源移动到列表末尾
DefaultPropertiesPropertySource.moveToEnd(environment);
// 确保environment中不包含environment-prefix属性
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
// 绑定environment和当前SpringApplication实例的关系
bindToSpringApplication(environment);
// 是否需要自定义environment,默认是false
if (!this.isCustomEnvironment) {
// 创建environmentConverter对象
EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
/*
* 将environment对象转换为目标类型的实例,deduceEnvironmentClass()主要是区分Servlet和Reactive。
* 因为是可以直接为SpringApplication实例设置environment属性的,所以这里是在确保设置的Environment类型和应用类型是一致的,
* 如果不一致,会自动进行转换。
*/
environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
// 这里为什么要再次attach?是为了确保configurationPropertySource位于列表中的第一个位置?
ConfigurationPropertySources.attach(environment);
return environment;
}
整个方法可以总结为下面的几个步骤:
- 获取或创建environment对象;
- 处理命令行参数;
- 处理配置属性源 ConfigurationPropertySources;
- 广播environmentPrepared事件;
- 处理默认属性源DefaultPropertiesPropertySource;
- 绑定environment和SpringApplication的关系;
- 自定义environment;
getOrCreateEnvironment方法
private ConfigurableEnvironment getOrCreateEnvironment() {
// 如果已存在,则直接返回
if (this.environment != null) {
return this.environment;
}
/*
* 如果不存在,则根据web应用类型创建不同类型的environment
* 对于ApplicationServletEnvironment和ApplicationReactiveWebEnvironment,两者的实现一样,
* 为什么不在这两者的基础上再抽象一层?
*/
switch (this.webApplicationType) {
case SERVLET:
return new ApplicationServletEnvironment();
case REACTIVE:
return new ApplicationReactiveWebEnvironment();
default:
return new ApplicationEnvironment();
}
}
这里利用到了SpringApplication构造阶段探测的web应用类型,对于不同类型的应用,创建不同的Environment对象。
class ApplicationServletEnvironment extends StandardServletEnvironment {
@Override
protected String doGetActiveProfilesProperty() {
return null;
}
@Override
protected String doGetDefaultProfilesProperty() {
return null;
}
@Override
protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
// 创建属性解析器
return ConfigurationPropertySources.createPropertyResolver(propertySources);
}
}
class ApplicationReactiveWebEnvironment extends StandardReactiveWebEnvironment {
@Override
protected String doGetActiveProfilesProperty() {
return null;
}
@Override
protected String doGetDefaultProfilesProperty() {
return null;
}
@Override
protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
// 创建属性解析器
return ConfigurationPropertySources.createPropertyResolver(propertySources);
}
}
上面两种Environment都只是重写了createPropertyResolver方法,而且实现一样,为什么需要实现子类,而且需要实现两个不同的类?可能的原因如下:
- 因为Spring Framework中的Environment并没有提供setPropertyResolver方法,而且外部也无法修改propertyResolver属性,所以只能实现子类来重写createPropertyResolver方法。
- servlet和reactive的environment是不同的类,也许是为后续的扩展留下空间。
public static ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
return new ConfigurationPropertySourcesPropertyResolver(propertySources);
}
ConfigurationPropertySourcesPropertyResolver(MutablePropertySources propertySources) {
this.propertySources = propertySources;
// 创建默认的解析器
this.defaultResolver = new DefaultResolver(propertySources);
}
/**
* Default {@link PropertySourcesPropertyResolver} used if
* {@link ConfigurationPropertySources} is not attached.
*/
// 这里的实现有什么意义?为什么不直接使用PropertySourcesPropertyResolver?
static class DefaultResolver extends PropertySourcesPropertyResolver {
DefaultResolver(PropertySources propertySources) {
super(propertySources);
}
@Override
public <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
return super.getProperty(key, targetValueType, resolveNestedPlaceholders);
}
}
这里并没有使用默认的属性解析器PropertySourcesPropertyResolver,而是ConfigurationPropertySourcesPropertyResolver。后者采用委托模式,组合了真正的属性解析器DefaultResolver。DefaultResolver继承于PropertySourcesPropertyResolver, 是ConfigurationPropertySourcesPropertyResolver中的内部类。
configureEnvironment方法
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
// 该属性默认为true
if (this.addConversionService) {
// 设置转换服务,用于转换属性,比如替换属性中的占位符
environment.setConversionService(new ApplicationConversionService());
}
// 设置属性源
configurePropertySources(environment, args);
// 设置Profiles,默认是空操作
configureProfiles(environment, args);
}
设置ConversionService
这里创建了一个转换服务对象,并设置到environment中的属性解析器中。在属性解析器解析属性时,如果需要对属性值进行转换,那么会调用转换服务。 这里创建的是ApplicationConversionService,会添加一些默认和预定义的转换器和格式化器。
public ApplicationConversionService() {
this(null);
}
public ApplicationConversionService(StringValueResolver embeddedValueResolver) {
this(embeddedValueResolver, false);
}
private ApplicationConversionService(StringValueResolver embeddedValueResolver, boolean unmodifiable) {
if (embeddedValueResolver != null) {
setEmbeddedValueResolver(embeddedValueResolver);
}
configure(this);
this.unmodifiable = unmodifiable;
}
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 addApplicationFormatters(FormatterRegistry registry) {
registry.addFormatter(new CharArrayFormatter());
registry.addFormatter(new InetAddressFormatter());
registry.addFormatter(new IsoOffsetFormatter());
}
在configure方法中,添加了默认的转换器和格式化器。那两个类是Spring Framework中的,这里就不贴出代码了,逻辑很简单,就是添加了一系列组件。在涉及到具体的类型转换和格式化问题时再有针对性地分析问题。
设置命令行参数属性源
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
// 从environment对象中获取属性源,==== 该方法的目的是把命令行参数注入到environment的属性中 ====
MutablePropertySources sources = environment.getPropertySources();
// 如果默认属性配置存在,则将其追加在sources对象中
if (!CollectionUtils.isEmpty(this.defaultProperties)) {
DefaultPropertiesPropertySource.addOrMerge(this.defaultProperties, sources);
}
// addCommandLineProperties属性默认为true
/*
* 注意,下面调用的SimpleCommandLinePropertySource构造器内部会对args进行解析
* 也可以发现其处理参数的顺序,命令行参数会被放在第一个的位置
*/
if (this.addCommandLineProperties && args.length > 0) {
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
if (sources.contains(name)) { // 如果存在名为commandLineArgs的属性
PropertySource<?> source = sources.get(name);
CompositePropertySource composite = new CompositePropertySource(name);
/*
* 这里创建名称为springApplicationCommandLineArgs的命令行属性源,
* 然后作为属性源添加到复合属性源中
*/
composite.addPropertySource(
new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
// 继续添加已存在的属性源
composite.addPropertySource(source);
// 替换已存在的同名属性源
sources.replace(name, composite);
}
else { // 如果不存在名为commandLineArgs的配置,则创建一个,并放在sources中的第一个位置
// 使用默认名称commandLineArgs
sources.addFirst(new SimpleCommandLinePropertySource(args));
}
}
}
ConfigurationPropertySources.attach方法
private static final String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties";
public static void attach(Environment environment) {
// 要求environment必须是可配置的
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
// 获取environment中的所有属性源
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
// 获取名为configurationProperties的属性源
PropertySource<?> attached = getAttached(sources);
// 如果attached这个属性源不存在,或者所封装的source不是environment中的属性源,那么新建一个对象。
if (attached == null || !isUsingSources(attached, sources)) {
// 创建新的配置属性源对象
attached = new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
// 将其他属性源封装为一个Spring的配置属性源
new SpringConfigurationPropertySources(sources));
}
// 从原有的属性源列表中移除掉
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
// 将配置属性源添加到列表中的第一个
sources.addFirst(attached);
}
private static boolean isUsingSources(PropertySource<?> attached, MutablePropertySources sources) {
return attached instanceof ConfigurationPropertySourcesPropertySource
// 这里是在判断attached这个属性源封装的source和参数sources是否是同一个对象
&& ((SpringConfigurationPropertySources) attached.getSource()).isUsingSources(sources);
}
static PropertySource<?> getAttached(MutablePropertySources sources) {
// 从属性源集合中获取名为configurationProperties的属性源
return (sources != null) ? sources.get(ATTACHED_PROPERTY_SOURCE_NAME) : null;
}
在prepareEnvironment方法中调用了两次该方法,第二次调用是确保配置属性源(configurationPropertySource)位于属性源列表中的第一个,因为可能在environmentPrepared事件的处理中往属性源列表头部添加其他属性源。
environmentPrepared事件
事件的发起和广播的代码请参考上面介绍的SpringApplicationRunListeners,不再赘述。这里重点关注一个与environment相关的监听器:EnvironmentPostProcessorApplicationListener。
EnvironmentPostProcessorApplicationListener
构造器
在其构造器中,加载了预配置的EnvironmentPostProcessor类型。
public EnvironmentPostProcessorApplicationListener() {
this(EnvironmentPostProcessorsFactory::fromSpringFactories, new DeferredLogs());
}
/**
* Create a new {@link EnvironmentPostProcessorApplicationListener} with post
* processors created by the given factory.
* @param postProcessorsFactory the post processors factory
*/
public EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory) {
this((classloader) -> postProcessorsFactory, new DeferredLogs());
}
EnvironmentPostProcessorApplicationListener(
Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory, DeferredLogs deferredLogs) {
this.postProcessorsFactory = postProcessorsFactory;
this.deferredLogs = deferredLogs;
}
static EnvironmentPostProcessorsFactory fromSpringFactories(ClassLoader classLoader) {
return new ReflectionEnvironmentPostProcessorsFactory(classLoader,
SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));
}
private final List<Class<?>> classes;
private ClassLoader classLoader;
private final List<String> classNames;
ReflectionEnvironmentPostProcessorsFactory(Class<?>... classes) {
this.classes = new ArrayList<>(Arrays.asList(classes));
this.classNames = null;
}
ReflectionEnvironmentPostProcessorsFactory(ClassLoader classLoader, String... classNames) {
this(classLoader, Arrays.asList(classNames));
}
ReflectionEnvironmentPostProcessorsFactory(ClassLoader classLoader, List<String> classNames) {
this.classes = null;
this.classLoader = classLoader;
this.classNames = classNames;
}
预配置的EnvironmentPostProcessor如下:
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
事件处理
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent();
}
if (event instanceof ApplicationFailedEvent) {
onApplicationFailedEvent();
}
}
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
SpringApplication application = event.getSpringApplication();
// 获取并遍历后置处理器
for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),
event.getBootstrapContext())) {
// 后置处理
postProcessor.postProcessEnvironment(environment, application);
}
}
List<EnvironmentPostProcessor> getEnvironmentPostProcessors(ResourceLoader resourceLoader,
ConfigurableBootstrapContext bootstrapContext) {
ClassLoader classLoader = (resourceLoader != null) ? resourceLoader.getClassLoader() : null;
EnvironmentPostProcessorsFactory postProcessorsFactory = this.postProcessorsFactory.apply(classLoader);
// 获取后置处理器
return postProcessorsFactory.getEnvironmentPostProcessors(this.deferredLogs, bootstrapContext);
}
@Override
public List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory,
ConfigurableBootstrapContext bootstrapContext) {
// 创建实例化器,用于实例化预配置的environment后置处理器类
Instantiator<EnvironmentPostProcessor> instantiator = new Instantiator<>(EnvironmentPostProcessor.class,
(parameters) -> {
parameters.add(DeferredLogFactory.class, logFactory);
parameters.add(Log.class, logFactory::getLog);
parameters.add(ConfigurableBootstrapContext.class, bootstrapContext);
parameters.add(BootstrapContext.class, bootstrapContext);
parameters.add(BootstrapRegistry.class, bootstrapContext);
});
return (this.classes != null) ? instantiator.instantiateTypes(this.classes)
// 创建classNames中的类型对应的实例
: instantiator.instantiate(this.classLoader, this.classNames);
}
public class Instantiator<T> {
private static final Comparator<Constructor<?>> CONSTRUCTOR_COMPARATOR = Comparator
.<Constructor<?>>comparingInt(Constructor::getParameterCount).reversed();
private static final FailureHandler throwingFailureHandler = (type, implementationName, failure) -> {
throw new IllegalArgumentException("Unable to instantiate " + implementationName + " [" + type.getName() + "]",
failure);
};
private final Class<?> type;
private final Map<Class<?>, Function<Class<?>, Object>> availableParameters;
private final FailureHandler failureHandler;
/**
* Create a new {@link Instantiator} instance for the given type.
* @param type the type to instantiate
* @param availableParameters consumer used to register available parameters
*/
public Instantiator(Class<?> type, Consumer<AvailableParameters> availableParameters) {
this(type, availableParameters, throwingFailureHandler);
}
/**
* Create a new {@link Instantiator} instance for the given type.
* @param type the type to instantiate
* @param availableParameters consumer used to register available parameters
* @param failureHandler a {@link FailureHandler} that will be called in case of
* failure when instantiating objects
* @since 2.7.0
*/
public Instantiator(Class<?> type, Consumer<AvailableParameters> availableParameters,
FailureHandler failureHandler) {
this.type = type;
this.availableParameters = getAvailableParameters(availableParameters);
this.failureHandler = failureHandler;
}
private Map<Class<?>, Function<Class<?>, Object>> getAvailableParameters(
Consumer<AvailableParameters> availableParameters) {
Map<Class<?>, Function<Class<?>, Object>> result = new LinkedHashMap<>();
availableParameters.accept(new AvailableParameters() {
@Override
public void add(Class<?> type, Object instance) {
result.put(type, (factoryType) -> instance);
}
@Override
public void add(Class<?> type, Function<Class<?>, Object> factory) {
result.put(type, factory);
}
});
return Collections.unmodifiableMap(result);
}
/*
* 注意下面的几个instantiate重载方法调用顺序是依次往后
*/
/**
* Instantiate the given set of class name, injecting constructor arguments as
* necessary.
* @param names the class names to instantiate
* @return a list of instantiated instances
*/
public List<T> instantiate(Collection<String> names) {
return instantiate((ClassLoader) null, names);
}
/**
* Instantiate the given set of class name, injecting constructor arguments as
* necessary.
* @param classLoader the source classloader
* @param names the class names to instantiate
* @return a list of instantiated instances
* @since 2.4.8
*/
public List<T> instantiate(ClassLoader classLoader, Collection<String> names) {
Assert.notNull(names, "Names must not be null");
return instantiate(names.stream().map((name) -> TypeSupplier.forName(classLoader, name)));
}
/**
* Instantiate the given set of classes, injecting constructor arguments as necessary.
* @param types the types to instantiate
* @return a list of instantiated instances
* @since 2.4.8
*/
public List<T> instantiateTypes(Collection<Class<?>> types) {
Assert.notNull(types, "Types must not be null");
return instantiate(types.stream().map(TypeSupplier::forType));
}
private List<T> instantiate(Stream<TypeSupplier> typeSuppliers) {
List<T> instances = typeSuppliers.map(this::instantiate).collect(Collectors.toList());
AnnotationAwareOrderComparator.sort(instances);
return Collections.unmodifiableList(instances);
}
private T instantiate(TypeSupplier typeSupplier) {
try {
Class<?> type = typeSupplier.get();
Assert.isAssignable(this.type, type);
// 创建实例对象,调用下一个instantiate重载方法
return instantiate(type);
}
catch (Throwable ex) {
this.failureHandler.handleFailure(this.type, typeSupplier.getName(), ex);
return null;
}
}
@SuppressWarnings("unchecked")
private T instantiate(Class<?> type) throws Exception {
Constructor<?>[] constructors = type.getDeclaredConstructors();
Arrays.sort(constructors, CONSTRUCTOR_COMPARATOR);
for (Constructor<?> constructor : constructors) {
// 获取构造方法参数列表
Object[] args = getArgs(constructor.getParameterTypes());
if (args != null) {
ReflectionUtils.makeAccessible(constructor);
// 创建实例对象
return (T) constructor.newInstance(args);
}
}
throw new IllegalAccessException("Class [" + type.getName() + "] has no suitable constructor");
}
private Object[] getArgs(Class<?>[] parameterTypes) {
Object[] args = new Object[parameterTypes.length];
// 遍历构造方法参数类型
for (int i = 0; i < parameterTypes.length; i++) {
// 获取可用的参数
Function<Class<?>, Object> parameter = getAvailableParameter(parameterTypes[i]);
if (parameter == null) {
return null;
}
// 获取实际的参数值
args[i] = parameter.apply(this.type);
}
return args;
}
private Function<Class<?>, Object> getAvailableParameter(Class<?> parameterType) {
// 遍历所有的可用参数
for (Map.Entry<Class<?>, Function<Class<?>, Object>> entry : this.availableParameters.entrySet()) {
// 如果可用参数的类型是目标类型及其子类型,
if (entry.getKey().isAssignableFrom(parameterType)) {
// 则返回对应的参数值对象
return entry.getValue();
}
}
return null;
}
/**
* Callback used to register available parameters.
*/
public interface AvailableParameters {
/**
* Add a parameter with an instance value.
* @param type the parameter type
* @param instance the instance that should be injected
*/
void add(Class<?> type, Object instance);
/**
* Add a parameter with an instance factory.
* @param type the parameter type
* @param factory the factory used to create the instance that should be injected
*/
void add(Class<?> type, Function<Class<?>, Object> factory);
}
/**
* {@link Supplier} that provides a class type.
*/
private interface TypeSupplier {
String getName();
Class<?> get() throws ClassNotFoundException;
static TypeSupplier forName(ClassLoader classLoader, String name) {
return new TypeSupplier() {
@Override
public String getName() {
return name;
}
@Override
public Class<?> get() throws ClassNotFoundException {
return ClassUtils.forName(name, classLoader);
}
};
}
static TypeSupplier forType(Class<?> type) {
return new TypeSupplier() {
@Override
public String getName() {
return type.getName();
}
@Override
public Class<?> get() throws ClassNotFoundException {
return type;
}
};
}
}
/**
* Strategy for handling a failure that occurs when instantiating a type.
*
* @since 2.7.0
*/
public interface FailureHandler {
/**
* Handle the {@code failure} that occurred when instantiating the {@code type}
* that was expected to be of the given {@code typeSupplier}.
* @param type the type
* @param implementationName the name of the implementation type
* @param failure the failure that occurred
*/
void handleFailure(Class<?> type, String implementationName, Throwable failure);
}
}
这里省略各个environment后置处理器的后置逻辑,需要单独写文章来介绍。
DefaultPropertiesPropertySource.moveToEnd 方法
public static final String NAME = "defaultProperties";
public static void moveToEnd(ConfigurableEnvironment environment) {
moveToEnd(environment.getPropertySources());
}
public static void moveToEnd(MutablePropertySources propertySources) {
// 移除默认属性源
PropertySource<?> propertySource = propertySources.remove(NAME);
if (propertySource != null) {
// 将默认属性源添加到列表末尾
propertySources.addLast(propertySource);
}
}
这部分的逻辑比较简单,就是把environment对象中名称为”defaultProperties“的属性源移动到列表末尾。
bindToSpringApplication方法
该方法主要是将当前的environment对象中的以spring.main开头的属性绑定到当前SpringApplication实例上。
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
try {
// 将spring.main开头的属性办定到当前类实例中
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
由于Binder的逻辑比较复杂,代码量较多,所以这里暂时省略,后续新写一篇文章来总结。
转换environment对象
由于是可以在SpringApplication外部设置environment对象的,所以如果不需要自定义environment的情况下,Spring Boot默认会将environment对象转换为根据应用类型而自动推断出来的Environment类型。
StandardEnvironment convertEnvironmentIfNecessary(ConfigurableEnvironment environment,
Class<? extends StandardEnvironment> type) {
// 如果environment对象就是目标类型的实例,
if (type.equals(environment.getClass())) {
// 则直接转换
return (StandardEnvironment) environment;
}
// 转换environment对象
return convertEnvironment(environment, type);
}
private StandardEnvironment convertEnvironment(ConfigurableEnvironment environment,
Class<? extends StandardEnvironment> type) {
// 创建目标类型的Environment实例
StandardEnvironment result = createEnvironment(type);
// 设置激活的profiles
result.setActiveProfiles(environment.getActiveProfiles());
// 设置转换服务
result.setConversionService(environment.getConversionService());
// 复制属性源
copyPropertySources(environment, result);
return result;
}
spring.beaninfo.ignore属性设置
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
// 如果不存在名为spring.beaninfo.ignore的系统属性,那么从environment中获取然后设置到系统属性中
if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
// 从environment中获取属性
Boolean ignore = environment.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
Boolean.class, Boolean.TRUE);
// 设置到系统属性中
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
}
}
应用上下文
接下来
createApplicationContext方法
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
protected ConfigurableApplicationContext createApplicationContext() {
/*
* applicationContextFactory的默认值是ApplicationContextFactory.DEFAULT,
* 但也可以通过setApplicationContextFactory方法来设置
*/
return this.applicationContextFactory.create(this.webApplicationType);
}
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
// 默认配置了两个,分别对应Servlet类型和Reactive类型的web应用
for (ApplicationContextFactory candidate : SpringFactoriesLoader
.loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader())) {
// 这里把web应用类型传进去,里面会基于web应用类型判断是否创建容器,类型不匹配的话会返回null
ConfigurableApplicationContext context = candidate.create(webApplicationType);
if (context != null) {
return context;
}
}
// 非web类型
return new AnnotationConfigApplicationContext();
}
catch (Exception ex) {
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory", ex);
}
};
这里会加载预配置好的应用上下文工厂类:
# Application Context Factories
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory
下面分别是两种应用上下文工厂的实现:
static class Factory implements ApplicationContextFactory {
// 创建servlet应用上下文实例
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.SERVLET) ? null
: new AnnotationConfigServletWebServerApplicationContext();
}
}
static class Factory implements ApplicationContextFactory {
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.REACTIVE) ? null
// 创建容器上下文
: new AnnotationConfigReactiveWebServerApplicationContext();
}
}
prepareContext方法
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 应用上下文关联environment对象
context.setEnvironment(environment);
// 应用上下文后置处理
postProcessApplicationContext(context);
// 执行应用上下文初始化器
applyInitializers(context);
/*
* 事件通知
* 在Spring Cloud中会执行到BootstrapApplicationListener
*/
listeners.contextPrepared(context);
// 关闭启动上下文
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null); // 打印启动日志
logStartupProfileInfo(context); // 打印profile日志
}
// Add boot specific singleton beans
// 获取beanFactory并注册springApplicationArguments、 printedBanner为单例bean,另外还设置是否允许循环依赖、是否允许覆盖beanDefinition的属性
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
// 设置是否允许循环依赖, 默认为false (boolean类型的默认值)。
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
// 设置是否允许覆盖beanDefinition的属性
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
// 下面添加bean工厂后置处理器
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
// Load the sources
// 获取全部配置源
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 将配置源中的bean注册到beanFactory中
load(context, sources.toArray(new Object[0]));
// 广播应用上下文加载完成事件
listeners.contextLoaded(context);
}
大部分步骤都很简单,主要分析一下后置处理器和初始化器的执行。
postProcessApplicationContext方法
private boolean addConversionService = true;
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
// 如果存在beanNameGenerator,那么注册到beanFactory上
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
// 如果存在resourceLoader,那么注册到applicationContext上
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
}
}
// (addConversionService默认为true)注册转换服务
if (this.addConversionService) {
context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
}
}
applyInitializers方法
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void applyInitializers(ConfigurableApplicationContext context) {
// 遍历应用上下文初始化器
for (ApplicationContextInitializer initializer : getInitializers()) {
// 获取当前initializer的泛型参数(这里是怎么获取到泛型参数的?)
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
// 断言泛型参数和context的类型是否匹配
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
// 初始化context
initializer.initialize(context);
}
}
public Set<ApplicationContextInitializer<?>> getInitializers() {
return asUnmodifiableOrderedSet(this.initializers);
}
这里执行的ApplicationContextInitializer是SpringApplication构造时从预配置文件中加载并实例化的。
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
refreshContext方法
static final SpringApplicationShutdownHook shutdownHook = new SpringApplicationShutdownHook();
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
shutdownHook.registerApplicationContext(context);
}
// 刷新上下文
refresh(context);
}
protected void refresh(ConfigurableApplicationContext applicationContext) {
/*
* 这里没有直接调用AbstractApplicationContext的refresh方法,
* 而是调用的ConfigurableApplicationContext(直接继承ApplicationContext)的refresh方法。
* 其有两个子类重写了该方法,在重写的方法中再调用的AbstractApplicationContext的refresh方法。
*/
applicationContext.refresh();
}
执行Runners
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
// 分别从应用上下文中获取ApplicationRunner和CommandLineRunner类型的bean
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
// 对其进行排序
AnnotationAwareOrderComparator.sort(runners);
// 遍历runner
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
// 调用ApplicationRunner
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
// 调用CommandLineRunner
callRunner((CommandLineRunner) runner, args);
}
}
}
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
总结
本文篇幅较长,主要的重点是Environment对象的处理和ApplicationContext的处理。Spring Boot的启动流程中涉及很多事件的发布,很多扩展都是基于这些事件来实现的,后续单独写文章来总结每种扩展点。