Spring Boot启动过程
Spring Boot启动过程
1. SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources)
- SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断web类型,此处是通过ClassUtils.isPresent()来读取类是否存在,决定环境类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 给定类型,然后从spring.factories文件加载初始化器
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
// 给定类型,然后从spring.factories文件加载初始化器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 使用StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(),
// 获取堆栈信息,获取名称为main方法的全类名,赋值
this.mainApplicationClass = deduceMainApplicationClass();
}
2.run(new Class<?>[] , args);
public ConfigurableApplicationContext run(String... args) {
// 1、创建并启动计时监控类
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2、初始化应用上下文和异常报告集合
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 3、设置系统属性 `java.awt.headless` 的值,默认值为:true
configureHeadlessProperty();
// 4、创建所有 Spring 运行监听器并发布应用启动事件
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 5、初始化默认应用参数类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 6、根据运行监听器和应用参数来准备 Spring 环境
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
// 7、创建 Banner 打印类
Banner printedBanner = printBanner(environment);
// 8、创建应用上下文
context = createApplicationContext();
// 9、准备异常报告器
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 10、准备应用上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 11、刷新应用上下文
refreshContext(context);
// 12、应用上下文刷新后置处理
afterRefresh(context, applicationArguments);
// 13、停止计时监控类
stopWatch.stop();
// 14、输出日志记录执行主类名、时间信息
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 15、发布应用上下文启动完成事件
listeners.started(context);
// 16、执行所有 Runner 运行器
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 17、发布应用上下文就绪事件
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
// 18、返回应用上下文
return context;
}
根据序号详细说明 : **
2、初始化应用上下文和异常报告集合
ConfigurableApplicationContext context = null;
//新建异常报告集合 ,在 `9、准备异常报告器` 中准备完成
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
3、设置系统属性 java.awt.headless
的值,默认值为:true
对于一个 Java 服务器来说经常要处理一些图形元素,例如地图的创建或者图形和图表等。这些API基本上总是需要运行一个X-server以便能使用AWT(Abstract Window Toolkit,抽象窗口工具集)。然而运行一个不必要的 X-server 并不是一种好的管理方式。有时你甚至不能运行 X-server,因此最好的方案是运行 headless 服务器,来进行简单的图像处理。
4、创建所有 Spring 运行监听器并发布应用启动事件
void starting();
void environmentPrepared(ConfigurableEnvironment environment);
void contextPrepared(ConfigurableApplicationContext context);
void contextLoaded(ConfigurableApplicationContext context);
void started(ConfigurableApplicationContext context);
void running(ConfigurableApplicationContext context);
void failed(ConfigurableApplicationContext context, Throwable exception);
4.1 listeners.starting()
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
//EventPublishingRunListener#starting()
listener.starting();
}
}
4.1.1 EventPublishingRunListener#starting()
// SimpleApplicationEventMulticaster initialMulticaster
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
多路广播事件处理 :
multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType)
-| invokeListener(listener, event)
-| doInvokeListener(listener, event)
-| listener.onApplicationEvent(event)注 : onApplicationEvent(event),其实看到此方法就可以见到真正处理的代码了!好开心!
6、根据运行监听器和应用参数来准备 Spring 环境
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
// listeners.`environmentPrepared(environment)` 与`4.1`节处理逻辑相似
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
10、准备应用上下文
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 设置环境
context.setEnvironment(environment);
// 回调方法,Spring容器创建之后做一些额外的事
postProcessApplicationContext(context);
// SpringApplication的的初始化器开始工作
applyInitializers(context);
// 遍历调用SpringApplicationRunListener的contextPrepared方法。
// 目前只是将这个事件广播器注册到Spring容器中
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);
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 读取主类数据loader.load();
load(context, sources.toArray(new Object[0]));
// 遍历调用SpringApplicationRunListener的contextLoaded方法。
listeners.contextLoaded(context);
}
11、*
刷新应用上下文
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 11.1 Prepare this context for refreshing.
prepareRefresh();
// 11.2 Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 11.3 Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 11.4 Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 11.5 Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// 11.6 Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 11.7 Initialize message source for this context.
initMessageSource();
// 11.8Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 11.9 Initialize other special beans in specific context subclasses.
onRefresh();
// 11.10 Check for listener beans and register them.
registerListeners();
// 11.11 Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 11.12 Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - "
"cancelling refresh attempt: " + ex);
}
// 11.13 Destroy already created singletons to avoid dangling resources.
destroyBeans();
// 11.14 Reset 'active' flag.
cancelRefresh(ex);
// 11.15 Propagate exception to caller.
throw ex;
}
finally {
// 11.16 Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
11.1 prepareRefresh();
-
设置Spring容器的启动时间,撤销关闭状态,开启活跃状态。
-
初始化属性源信息(Property)
-
验证环境信息里一些必须存在的属性
11.3 prepareBeanFactory(beanFactory);
- 设置classloader(用于加载bean),设置表达式解析器(解析bean定义中的一些表达式),添加属性编辑注册器(注册属性编辑器)
- 添加ApplicationContextAwareProcessor这个BeanPostProcessor。取消ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、EnvironmentAware这5个接口的自动注入。因为ApplicationContextAwareProcessor把这5个接口的实现工作做了
- 设置特殊的类型对应的bean。BeanFactory对应刚刚获取的BeanFactory;ResourceLoader、ApplicationEventPublisher、ApplicationContext这3个接口对应的bean都设置为当前的Spring容器
- 注入一些其它信息的bean,比如environment、systemProperties等
11.5 invokeBeanFactoryPostProcessors(beanFactory);
**调用链路 : **
invokeBeanFactoryPostProcessors(beanFactory)
--->
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors())
--->
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
postProcessor.postProcessBeanDefinitionRegistry(registry)
--->
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
processConfigBeanDefinitions(registry)
[创建config bean]--->
**读取主类包中的@Component注解 : **
ComponentScanAnnotationParser
读取@ComponentScan
注解,通过parse()
加载packages
属性.
Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass)
declaringClass
是传入的主类,默认会读取该类的包位置