前言
SpringBoot的启动过程比较长,会涉及到其他模块的事件/监听器,这些监听器里又会有自己的逻辑;本文重点集中在启动过程上,对于比较重要的,对全局有影响的监听器也会单独拎出,说明它的作用。文章很长,先给出启动的大致流程:
启动类
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
SpringApplication#run(java.lang.Class<?>, java.lang.String...)
这个方法有两步:
- 创建
SpringApplication
; - 调用
run
方法;
new SpringApplication()
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 从spring.factories里搜索`ApplicationContextInitializer`类
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 从spring.factories里搜索`ApplicationListener`类
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
run
方法
run
方法就比较重要了。这里先概览下,下面再分步慢慢分析。
public ConfigurableApplicationContext run(String... args) {
// 计数秒表
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 从spring.factories里搜索`SpringApplicationRunListener`类
// 会找到`EventPublishingRunListener`
SpringApplicationRunListeners listeners = getRunListeners(args);
// 调用`SpringApplicationRunListener`里的`starting`方法
// 在`EventPublishingRunListener`里会构建一个`ApplicationStartingEvent`事件
// 并找出监听该事件的监听器然后调用
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
// 会将启动命令里的变量以及系统的环境变量放到两个PropertiesPropertySource里
// 将该环境对象绑定到当前的`SpringApplication`上
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 取环境变量里的`spring.beaninfo.ignore`,并将其设置到系统对象里去
configureIgnoreBeanInfo(environment);
// 打印banner,可通过`spring.banner.location`属性执行自己的banner
Banner printedBanner = printBanner(environment);
// 创建`ConfigurableApplicationContext`
context = createApplicationContext();
// 从spring.factories里搜索`SpringBootExceptionReporter`类
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
// 在`SpringApplication`中,该方法为空方法
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 调用`SpringApplicationRunListener`里的`running`方法
// 在`EventPublishingRunListener`里会构建一个`ApplicationReadyEvent`事件
// 并找出监听该事件的监听器然后调用
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
下面会以listeners.starting
、prepareEnvironment
、createApplicationContext
、prepareContext
、refreshContext
为入口依次分析。
EventPublishingRunListener
在run
的方法里注释里我们提到目前的SpringApplicationRunListener
只找到一个EventPublishingRunListener
:
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster
.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster
.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
...
}
从上面的代码可以看出,EventPublishingRunListener
是作为一个广播器的存在,构造事件并将事件广播给符合条件的监听器。
listeners.starting
listeners.starting
是发出了一个ApplicationStartingEvent
事件,通过断点我们可以看到有以下几个监听器监听了改事件:
LoggingApplicationListener
: 获取日志系统,选项有:ch.qos.logback.core.Appender
,org.apache.logging.log4j.core.impl.Log4jContextFactory
,java.util.logging.LogManager
; 并执行beforeInitialize
将日志系统重置为限制输出BackgroundPreinitializer
: 对于一些耗时的任务使用一个后台线程尽早触发它们开始执行初始化
prepareEnvironment
先看下它的方法体:
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 创建环境对象
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 根据启动参数配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 给`environment`附件一个`ConfigurationPropertySource`
ConfigurationPropertySources.attach(environment);
// 调用`SpringApplicationRunListener`里的`environmentPrepared`方法
// 在`EventPublishingRunListener`里会构建一个`ApplicationEnvironmentPreparedEvent`事件
// 并找出监听该事件的监听器然后调用
listeners.environmentPrepared(environment);
// 将`environment`对象绑定到当前的`SpringApplication`
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
// 将`environment`转换成`StandardServletEnvironment`类型
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
// 重新给`environment`附件一个`ConfigurationPropertySource`
ConfigurationPropertySources.attach(environment);
return environment;
}
下面我们要一个个方法进去进行细致的分析。
getOrCreateEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
// 我们这里的webApplicationType是SERVLET
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
继续探索new StandardServletEnvironment()
时做了什么工作:
public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment {
@Override
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);
}
@Override
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}
}
发现没有构造函数,我们继续找他的父类:
public class StandardEnvironment extends AbstractEnvironment {
@Override
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()));
}
}
依旧没有,继续向上:
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
private final MutablePropertySources propertySources = new MutablePropertySources();
private final ConfigurablePropertyResolver propertyResolver =
new PropertySourcesPropertyResolver(this.propertySources);
public AbstractEnvironment() {
customizePropertySources(this.propertySources);
}
}
找到了,在构造函数里调用了customizePropertySources
方法。我们再往回看知道它加了两个StubPropertySource
,又调用了父类的customizePropertySources
加了一个PropertiesPropertySource
和SystemEnvironmentPropertySource
,这两个PropertySource
分别保存启动命令里的变量以及系统环境变量。
configureEnvironment
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
// 在`SpringApplication`中为true
// 设置了一个`ApplicationConversionService`,满足大多数`springboot`应用的类型转换与格式化需求
//
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
// 添加来自命令行的属性
configurePropertySources(environment, args);
// 添加额外的配置文件到环境对象去
// 已有的配置文件从`spring.profiles.active`属性里获取
// 额外的配置文件是当前`SpringApplication`里的`additionalProfiles`值
configureProfiles(environment, args);
}
现在我们看下ApplicationConversionService
给我们预置了哪些converter
与formatter
:
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());
ConfigurationPropertySources.attach
public static void attach(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
// 获取环境对象里名为`ATTACHED_PROPERTY_SOURCE_NAME`的`PropertySource`
// 从`getOrCreateEnvironment`方法的分析我们可以看到,当时并没有添加这个`PropertySource`
PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
if (attached != null && attached.getSource() != sources) {
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
attached = null;
}
// 给环境对象添加`ConfigurationPropertySourcesPropertySource`
// 将当前已有的`PropertySource`设置到`ConfigurationPropertySourcesPropertySource`里去
// 目前还不知道为什么要这样设计
if (attached == null) {
sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
new SpringConfigurationPropertySources(sources)));
}
}
listeners.environmentPrepared
通过断点,发现目前的SpringApplicationRunListener
只有一个EventPublishingRunListener
,所以我们直接看EventPublishingRunListener
里的environmentPrepared
方法。
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster
.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
创建了一个ApplicationEnvironmentPreparedEvent
,然后多播:
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
通过断点,我们知道有以下几个org.springframework.boot
内置的监听器监听了ApplicationEnvironmentPreparedEvent
事件:
ConfigFileApplicationListener
:委派给EnvironmentPostProcessor
,通过从众所周知的文件位置加载属性来配置上下文环境:SystemEnvironmentPropertySourceEnvironmentPostProcessor
将environment
里的SystemEnvironmentPropertySource
替换为OriginAwareSystemEnvironmentPropertySource
[ps: 不知道为什么要替换]SpringApplicationJsonEnvironmentPostProcessor
将spring.application.json
/SPRING_APPLICATION_JSON
的值以JSON
的方式解析,并将key-value放入配置中。ConfigFileApplicationListener
,通过PropertiesPropertySourceLoader
/YamlPropertySourceLoader
加载配置文件中的配置项,使用PropertySourcesPlaceholdersResolver
处理占位符。
AnsiOutputApplicationListener
: 在控制台打印彩色日志LoggingApplicationListener
: 初始化日志系统,- 设置logfile以及各个package的日志level
- 根据
logging.register-shutdown-hook
配置判断是否需要注册Shutdown
事件的钩子。
ClasspathLoggingApplicationListener
: 以debug
级别记录线程上下文类加载器 (TCCL) 的类路径DelegatingApplicationListener
: 将事件委派context.listener.classes
指定的事件监听器FileEncodingApplicationListener
: 当文件系统的编码与预期不符时,会终止应用的启动。预期编码通过spring.mandatory-file-encoding
指定/获取,文件系统编码通过file.encoding
指定/获取。
bindToSpringApplication
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
try {
// 将`environment`对象绑定到当前的`SpringApplication`对象上
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
ConfigurationPropertySources.attach
prepareEnvironment
最后又执行了一次ConfigurationPropertySources.attach
;根据代码可以看出,这次执行会将上一步添加ATTACHED_PROPERTY_SOURCE_NAME
从environment
对象里移除。
小结
这节我们梳理了启动过程中的准备环境这一步,下面给出流程图:
createApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
// org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
// org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
我们使用SERVLET
:
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext{
// 创建了`AnnotatedBeanDefinitionReader`以及`ClassPathBeanDefinitionScanner`
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
// AnnotationConfigServletWebServerApplicationContext
<- ServletWebServerApplicationContext
<- GenericWebApplicationContext
<- GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
}
createApplicationContext
方法是非常简单的,单独拎出来是想看看他的构造函数里做了什么。
prepareContext
准备上下文
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 将准备好的环境对象设置到context里
context.setEnvironment(environment);
// 设置context里的`resourceLoader`/`classLoader`
// 设置context.beanFactory里的`beanNameGenerator`以及`conversionService`
postProcessApplicationContext(context);
// 依次调用`ApplicationContextInitializer`的`initialize`方法
applyInitializers(context);
// 向事件监听器发布`ApplicationContextInitializedEvent`事件
// 目前系统中并没有这样的监听器
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
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());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 将Bean Definition加载到context去
load(context, sources.toArray(new Object[0]));
// 向事件监听器发布`ApplicationPreparedEvent`事件
listeners.contextLoaded(context);
}
context.setEnvironment()
& postProcessApplicationContext
context.setEnvironment()
& postProcessApplicationContext
这两个方法比较直观,没有那么多弯弯绕绕。
// context.setEnvironment
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
// 创建一个ConditionEvaluator
// ConditionEvaluator评估有@ConditionOnXXX注解的组件类是否需要注册
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
// postProcessApplicationContext
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
// 目前的`beanNameGenerator`与`resourceLoader`都为null
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
}
}
// ApplicationConversionService在`prepareEnvironment`阶段已生成
// 这里拿到当时创建的单例设置到beanFactory里去
if (this.addConversionService) {
context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
}
}
applyInitializers
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
initializers在SpringApplication构造函数里已获得:
DelegatingApplicationContextInitializer
: 委派给context.listener.classes
指定的初始化器进行处理ContextIdApplicationContextInitializer
: 以spring.application.name
为ID, 创建一个ContextId
,并以单例的方式注册到contextConditionEvaluationReportLoggingListener
: 向context添加ConditionEvaluationReportListener
监听器,在接受到事件ContextRefreshedEvent
与ApplicationFailedEvent
时,以debug
的等级记录条件评估(ConditionEvaluation
)的详细信息ConfigurationWarningsApplicationContextInitializer
: 报告常见错误配置的警告ServerPortInfoApplicationContextInitializer
: 向context添加一个监听WebServerInitializedEvent
事件的监听器(ps: 其实就是它自己)
load
将 bean 加载到应用程序上下文中。
// 这里的sources是我们的启动类
protected void load(ApplicationContext context, Object[] sources) {
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
// `beanNameGenerator`/`resourceLoader`/`environment`为null
...
loader.load();
}
protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
return new BeanDefinitionLoader(registry, sources);
}
BeanDefinitionLoader
class BeanDefinitionLoader {
// 需要注意使用的reader/scanner类
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
int load() {
int count = 0;
for (Object source : this.sources) {
count += load(source);
}
return count;
}
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class<?>) {
return load((Class<?>) source);
}
...
}
private int load(Class<?> source) {
// Groovy
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
...
}
// 非匿名类、非Groove闭包、有无参构造函数
if (isEligible(source)) {
// 在`AnnotatedBeanDefinitionReader`一节中,我们知道`annotatedReader`的类是`AnnotatedBeanDefinitionReader`
this.annotatedReader.register(source);
return 1;
}
return 0;
}
private boolean isEligible(Class<?> type) {
return !(type.isAnonymousClass() || isGroovyClosure(type) || hasNoConstructors(type));
}
...
}
AnnotatedBeanDefinitionReader
public class AnnotatedBeanDefinitionReader {
// 这里的componentClasses只有一个当前项目的启动类
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 通过`@ConditionXXX`注解判断是否要加载
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 根据类上的`Lazy`/`Primary`/`DependsOn`/`Role`/`Description`注解,设置相应的abd属性
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
...
}
if (customizers != null) {
...
}
// 将启动类的BeanDefinition封装成BeanDefinitionHolder,并将其注册到`registry`[其实就是context]
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
listeners.contextLoaded
上文已述在当前的SpringApplication
中listeners
里只有一个元素-EventPublishingRunListener
,这个类里的contextLoaded
方法将SpringApplication
对象里的ApplicationListener
数组先同步到context里,再广播ApplicationPreparedEvent
事件:
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
通过断点,我们知道有以下几个org.springframework.boot
内置的监听器监听了ApplicationPreparedEvent
事件:
ConfigFileApplicationListener
:添加PropertySourceOrderingPostProcessor
; 将Environment对象中的缺省属性源(名为"defaultProperties")放到最低优先级LoggingApplicationListener
: 将准备好的日志相关的对象注册为单例DelegatingApplicationListener
: 将事件委派context.listener.classes
指定的事件监听器
小结
这节我们梳理了启动过程中的准备上下文这一步,下面给出流程图:
refreshContext
刷新应用上下文
对refreshContext
进行调用链追踪,它的真实面目就是org.springframework.context.support.AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新
// 会进行一些数据清理以及校验
prepareRefresh();
// 获取beanFactory对象
// 在当前的context中是设置beanFactory的serializationId,并返回
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备在此上下文中使用的bean工厂。
prepareBeanFactory(beanFactory);
try {
// 在子类里对beanFactory进行后置处理
postProcessBeanFactory(beanFactory);
// 执行已注册为bean的beanFactory后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 实例化和注册所有BeanPostProcessor bean
registerBeanPostProcessors(beanFactory);
// 初始化MessageSource
// MessageSource是用于解析消息的策略接口,支持此类消息的参数化和国际化。
initMessageSource();
// 初始化ApplicationEventMulticaster。
//如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。
initApplicationEventMulticaster();
// 初始化特定的bean
onRefresh();
// 添加实现ApplicationListener的bean
registerListeners();
// 实例化所有剩余的(non-lazy-init)单例对象
finishBeanFactoryInitialization(beanFactory);
// 完成此上下文的刷新
// 调用 LifecycleProcessor 的 onRefresh() 方法并发布 ContextRefreshedEvent事件
finishRefresh();
}
catch (BeansException ex) {
...
}
finally {
// 重置Spring的公共反射元数据缓存,特别是ReflectionUtils, AnnotationUtils, ResolvableType和CachedIntrospectionResults缓存。
resetCommonCaches();
}
}
}
下面会从prepareRefresh
、prepareBeanFactory
、postProcessBeanFactory
、invokeBeanFactoryPostProcessors
、registerBeanPostProcessors
、initMessageSource
、initApplicationEventMulticaster
、onRefresh
、registerListeners
、finishBeanFactoryInitialization
、finishRefresh
依次进行分析,比较简单的方法会放在一起。
prepareRefresh
刷新前准备
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
...
// 初始化上下文环境中的任何占位符属性源
// 还记得在`准备环境`一节中,创建Environment[StandardServletEnvironment]对象时添加的两个`StubPropertySource`吗
// 这一步就是想要替换这两个PropertySource
// 但是由于当前context的`servletContext`与`servletConfig`都为null,所以并没有替换
initPropertySources();
// 验证所有标记为required的属性都是可解析的
// 目前没有属性被标记为required
getEnvironment().validateRequiredProperties();
// 将`applicationListeners`元素复制到`earlyApplicationListeners`
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 初始化`earlyApplicationEvents`属性
this.earlyApplicationEvents = new LinkedHashSet<>();
}
obtainFreshBeanFactory
& prepareBeanFactory
这两个方法比较简单:
obtainFreshBeanFactory
就是指定context里beanFactory
里的serializationId
,并将其返回;prepareBeanFactory
:配置beanFactory
的属性,如:beanClassLoader
、beanPostProcessor
、beanExpressionResolver
等以及设置不自动装配的接口和使用指定的值去自动装配指定的类型:protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); ... }
postProcessBeanFactory
在应用程序上下文的标准初始化之后修改其内部beanFactory
:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 执行父类的`postProcessBeanFactory`
// 这里的父类是`ServletWebServerApplicationContext`
super.postProcessBeanFactory(beanFactory);
// 我们的启动类里未指定`basePackages`
// 这里不执行`scan`
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
// `annotatedClasses`为空,这里不执行`register`
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
ServletWebServerApplicationContext#postProcessBeanFactory
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加一个`BeanPostProcessor`
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
// 设置`ServletContextAware`的依赖不自动装配
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
// 注册Web应用的作用域
// web应用的作用域有:`request`/`session`/`application`
registerWebApplicationScopes();
}
invokeBeanFactoryPostProcessors
执行后置处理器
实例化和调用所有已注册的BeanFactoryPostProcessor:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 这里会执行两种后置处理
// 1. postProcessBeanDefinitionRegistry
// 2. postProcessBeanFactory
// `getBeanFactoryPostProcessors`会得到3个`BeanFactoryPostProcessor`
// - SharedMetadataReaderFactoryContextInitializer.CachingMetadataReaderFactoryPostProcessor
// - ConfigurationWarningsApplicationContextInitializer.ConfigurationWarningsPostProcessor
// - ConfigFileApplicationListener.PropertySourceOrderingPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 设置`beanFactory`属性
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
下面我们详细看下PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
方法,这个方法很长:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
// 这里用的`beanFactory`是`DefaultListableBeanFactory`属于`BeanDefinitionRegistry`
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 在上文提到的三个postProcessor中,`CachingMetadataReaderFactoryPostProcessor`与`ConfigurationWarningsPostProcessor`都属于`BeanDefinitionRegistryPostProcessor`
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// ConfigurationWarningsPostProcessor在该方法里检查了@ComponentScan里设置的包[不能在'org'/'org.springframework'中]
// CachingMetadataReaderFactoryPostProcessor添加了一个名为`org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory`的`SharedMetadataReaderFactoryBean`
// 以及设置`org.springframework.context.annotation.internalConfigurationAnnotationProcessor`的`metadataReaderFactory`属性[为一个`RuntimeBeanReference`]
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 调用实现了`PriorityOrdered`的`BeanDefinitionRegistryPostProcessor`的`postProcessBeanDefinitionRegistry`方法
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 调用实现了`Ordered`的`BeanDefinitionRegistryPostProcessor`的`postProcessBeanDefinitionRegistry`方法[与上面重复的不加入currentRegistryProcessors]
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
//执行其他未执行过的`BeanDefinitionRegistryPostProcessor`
// 为什么`postProcessorNames`要多次获取呢?
// `getBeanNamesForType`设置了缓存,且在执行各个`beanDefinitionRegistryPostProcessors`方法时,有可能会添加BeanDefinition
BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// 执行各个后置处理器的`beanFactoryPostProcessors`方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 有漏掉的`BeanFactoryPostProcessor`,根据是否有实现PriorityOrdered/Ordered接口进行顺序调用`postProcessBeanFactory`方法
// 会根据`processedBeans`跳过已执行过的后置处理器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清除缓存
beanFactory.clearMetadataCache();
}
BeanDefinitionRegistryPostProcessor
下面罗列用到的BeanDefinitionRegistryPostProcessor
以及说明它们的具体作用:
只考虑springboot自带的, 暂不考虑其他组件引入的
BeanDefinitionRegistryPostProcessor
ConfigurationClassPostProcessor
: 该后置处理器会先载入当前beanFactory
中有@Configuration
注解的类;然后遍历找到的类,按序解析其上的@Component
/@PropertySource
/@ComponentScan
注解,并递归解析@ComponentScan
扫描到的@Component
;再然后载入libraries里jar包下spring.factories
中的EnableAutoConfiguration
;最后解析类里的带@Bean
的方法,类上的@ImportResource
注解引入的xml文件以及@Import
导入的ImportBeanDefinitionRegistrar
。我们的启动类就是其中的一个@Configuration
类,启动类上的@SpringBootApplication
注解是个复合注解,里面就有@ComponentScan
,所以在这一步,我们将应用层的各种beanDefinition
载入到beanFactory
;
BeanFactoryPostProcessor
下面罗列用到的BeanFactoryPostProcessor
以及说明它们的具体作用:
只考虑springboot自带的, 暂不考虑其他组件引入的
BeanFactoryPostProcessor
ConfigurationClassPostProcessor
: 使用ConfigurationClassEnhancer
增强Configuration
类来支持@Bean
定义的bean scope,并添加一个ImportAwareBeanPostProcessor
后置处理器;ConfigFileApplicationListener
: 将默认的配置文件放到PropertySource
列表的最后面;PropertySourcesPlaceholderConfigurer
: 通过创建一个StringValueResolver
对象,处理容器里bean别名中的${...}
占位符,再将StringValueResolver
对象添加到beanFactory
的embeddedValueResolvers
列表里,后续处理@Value
、配置、注解中的${...}
占位符;EventListenerMethodProcessor
: 这个类的作用是将@EventListener
方法封装成一个个独立的ApplicationListener
实例;在postProcessBeanFactory
方法中先实例化EventListenerFactory
的bean;PreserveErrorControllerTargetClassPostProcessor
: 通过给ErrorController
的beanDefinition
设置preserveTargetClass
为true
来确保在使用AOP时保留它的目标类
registerBeanPostProcessors
实例化容器里的BeanPostProcessor
类,并按序加入到beanFactory
的beanPostProcessors
。下面我们看下系统预置的这些BeanPostProcessor
会有什么作用:
ApplicationContextAwareProcessor
: 如果一个bean有实现部分Aware
接口,在bean初始化调用其相应的设置方法;WebApplicationContextServletContextAwareProcessor
: 将servletContext
/servletConfig
分别传递给ServletContextAware
/ServletConfigAware
对象;ImportAwareBeanPostProcessor
: 设置ImportAware
的importMetadata
BeanPostProcessorChecker
: 当一个bean是在BeanPostProcessor
实例化期间创建的,通过这个处理器记录;ConfigurationPropertiesBindingPostProcessor
: 解析bean上的注解@ConfigurationProperties,将属性源中的属性设置到bean。AnnotationAwareAspectJAutoProxyCreator
: AOP入口,详情可查看之前的文章:Spring之AOP源码;DataSourceInitializerPostProcessor
: 强制初始化DataSourceInitializer
在DataSource
初始化时。AsyncAnnotationBeanPostProcessor
: 向有@Async
注解的类或方法添加AsyncAnnotationAdvisor
增强,用于异步执行;RabbitListenerAnnotationBeanPostProcessor
: 通过解析bean或bean方法上的@RabbitListener
/@RabbitHandler
注解,添加RabbitListenerEndpoint
实例;MethodValidationPostProcessor
: 对符合条件的bean添加一个MethodValidationInterceptor
增强,达到对有@Validated
的类、方法、属性进行校验;PersistenceExceptionTranslationPostProcessor
: 对符合条件的bean添加一个PersistenceExceptionTranslationAdvisor
,用于转换持久化异常信息;WebServerFactoryCustomizerBeanPostProcessor
: 将载入的WebServerFactory
bean应用到WebServerFactoryCustomizer
去;ErrorPageRegistrarBeanPostProcessor
: 将载入的ErrorPageRegistry
bean应用到ErrorPageRegistry
去;ProjectingArgumentResolverBeanPostProcessor
: 将ProxyingHandlerMethodArgumentResolver
加入到载入的RequestMappingHandlerAdapter
bean的ArgumentResolvers
列表第一个;ConfigurationPropertiesBeans
: 收集有@ConfigurationProperties
的bean;ApplicationListenerDetector
:ApplicationListener
探测器,如果载入的bean是ApplicationListener
就将其加入在context的applicationListeners
列表里;
initMessageSource
& initApplicationEventMulticaster
initMessageSource
:初始化MessageSource
,用于处理国际化场景;initApplicationEventMulticaster
:创建一个SimpleApplicationEventMulticaster
并添加到beanFactory;
onRefresh
protected void onRefresh() {
// 初始化主题功能
// 这里不再深入了
super.onRefresh();
try {
// 创建web服务
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
createWebServer
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
// 一开始webServer为null
if (webServer == null && servletContext == null) {
// 本文使用的是`TomcatServletWebServerFactory`
ServletWebServerFactory factory = getWebServerFactory();
// 创建WebServer
// 其实在这一步tomcat服务器已经启动了,但是我们的应用还未完全准备好,尚不能对外提供服务
// 这里的过程比较长,会单开一篇文章分析
this.webServer = factory.getWebServer(getSelfInitializer());
// 往beanFactory里注册两个单例:webServerGracefulShutdown、webServerStartStop
// 这两个都是实现了`SmartLifecycle`接口
// WebServer将在`WebServerStartStopLifecycle`的start回调里启动
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
// 这个方法之前也出现过,只不过当时的`servletContext`与`servletConfig`都为null
// 在这里通过`getWebServer`方法,`servletContext`被设置为`ApplicationContextFacade`
// 替换之前的占位`PropertySource`: servletContextInitParams
initPropertySources();
}
registerListeners
注册ApplicationListener
添加实现ApplicationListener作为侦听器的bean:
protected void registerListeners() {
// 将之前载入的`ApplicationListener`[来源有从`spring.factories`中读取,也有在事件监听器里添加的]
// 添加到`ApplicationEventMulticaster`去
// `ApplicationEventMulticaster`是在`initApplicationEventMulticaster`这边创建的`SimpleApplicationEventMulticaster`
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 从容器的BeanDefinition里找出实现`ApplicationListener`接口的beanName
// 注意,这里还只是beanName,并不是bean
// 后面有需要的时候,再实例化真正的bean
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 如果有早期的事件,在这里先广播
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
finishBeanFactoryInitialization
完成非lazy-init bean的初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 将beanName为`conversionService`的bean,设置到beanFactory的`conversionService`属性
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 在`invokeBeanFactoryPostProcessors`方法的解析里
// 我们有提到`PropertySourcesPlaceholderConfigurer`这个`BeanFactoryPostProcessor`
// 会添加一个`StringValueResolver`到beanFactory的`embeddedValueResolver`列表里
// 所以这里就不必再生成一个`StringValueResolver`了
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 预先加载`LoadTimeWeaverAware`
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
beanFactory.setTempClassLoader(null);
// 冻结所有的bean definition,不期望做进一步的改变
// 这里的冻结就是将beanFactory的`configurationFrozen`置为true
// 然后将所有beanDefinitionNames复制到beanFactory的`frozenBeanDefinitionNames`属性去
beanFactory.freezeConfiguration();
// 实例化剩余未实例化的非懒加载的单例bean
// 实例化完成后,再对实现`SmartInitializingSingleton`接口的bean,回调它的`afterSingletonsInstantiated`方法
// 如何实例化,这里先不展开了
beanFactory.preInstantiateSingletons();
}
finishRefresh
完成上下文的刷新,调用LifecycleProcessor
的onRefresh()
方法并发布contextrefreshdevent
事件。
protected void finishRefresh() {
// 清理资源缓存
clearResourceCaches();
// 初始化`LifecycleProcessor`
// 即:若当前beanFactory里存在`LifecycleProcessor`的实例或者bean definition就进行实例化;
// 若不存在就创建一个`DefaultLifecycleProcessor`对象
// 将最终获取的对象放入beanFactory的`lifecycleProcessor`属性里
initLifecycleProcessor();
// 调用`LifecycleProcessor`的onRefresh方法
// 在`DefaultLifecycleProcessor`中,该方法从容器里获取`Lifecycle`类型的bean
// 并依次调用他们的`start`方法
// 其中就有webServer的start
getLifecycleProcessor().onRefresh();
// 发布`ContextRefreshedEvent`事件
// 与web服务相关的一个监听器是`ResourceUrlProvider`,这个监听器`ContextRefreshedEvent`事件里初始化静态资源的访问路径
publishEvent(new ContextRefreshedEvent(this));
// 将当前上下文放入`MBean`(MBean如果可用的话)
LiveBeansView.registerApplicationContext(this);
}
小结
refreshContext
可以说是启动过程的重点了,涉及了web服务启动,IOC等;前面写的过程也很长,下面通过一个流程图,来回忆与总结下:
收尾
接下来的操作比较直观了:
- 调用
SpringApplicationRunListener``started
方法,当前context对象里这种类型的监听器只有EventPublishingRunListener
;EventPublishingRunListener
会构造一个ApplicationStartedEvent
事件并广播出去;发布应用状态变更事件LivenessState.CORRECT
; - 获取容器中的
ApplicationRunner
以及CommandLineRunner
,并依次调用; - 调用
SpringApplicationRunListener``running
方法,当前context对象里这种类型的监听器只有EventPublishingRunListener
;EventPublishingRunListener
会构造一个ApplicationReadyEvent
事件并广播出去;发布应用状态变更事件ReadinessState.ACCEPTING_TRAFFIC
;