Spring Boot 工程的主函数
@SpringBootApplication()
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(WhidsSsApplication.class, args);
}
}
分为了两个部分:
- 初始化
SpringApplication
new SpringApplication
- 运行
SpringApplication
springApplication.run()
1. 初始化 SpringApplication
配置基本的环境变量、资源、构造器、监听器。
初始化阶段的主要作用是为运行 SpringApplication 实例对象启动环境变量准备、以及进行资源构造器的初始化动作。
@SuppressWarnings({ "unchecked", "rawtypes" })
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();
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
setInitializers,实例化所有初始器:
加载ApplicationContextInitializer是在SpringFactoriesLoader.loadFactoryNames方法里面进行的。这个方法会尝试从类路径的META-INF/spring.factories读取相应配置文件,然后进行遍历,读取配置文件中Key为:org.springframework.context.ApplicationContextInitializer的 value。
以 spring-boot 为例,它的Initializers定义如下,Initializers的作用在上一章中已详细解释
# 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
setListeners,实例化所有监听器
同样以 spring-boot 为例,它的 Initializers 定义如下:
# 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
2. 运行 SpringApplication
Spring Boot 正式启动加载过程,包括启动流程监控模块、配置环境加载模块、ApplicationContext 容器上下文环境加载模块。
其中的一些关键步骤:
- 发布应用启动过程中的一系列事件
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
SpringApplicationRunListeners 本质上是一个事件发布者,它在 SpringBoot 应用启动的不同时间点发布不同应用事件类型(ApplicationEvent):

由上文知在初始化的流程中,SpringApplication 加载了一系列 ApplicationListener,其监听的事件就是在这里发布的。
- 创建应用程序上下文
即ApplicationContext,也就是我们所说的 Spring Ioc 容器,是在 BeanFactory 的基础之上的一种更高级的容器,除了具有基本的 bean 管理功能之外,还提供对事件监听机制以及国际化的支持等。
context = createApplicationContext();
- 准备
ApplicationContext
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
主要完成以下工作:
- 实例化单例的
BeanNameGenerator
// public static final String CONFIGURATION_BEAN_NAME_GENERATOR =
// "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
Spring 定义 bean 有两种模式:配置文件(xml,properties)和注解。BeanNameGenerator 是为 bean 定义生成 bean 名称的策略接口。
其实现类有两个:
DefaultBeanNameGenerator :用来处理 xml 资源文件,但一般情况下在 Spring Boot 中我们很少使用 xml 来引入 bean;
AnnotationBeanNameGenerator :处理 @Component 等注解生成 bean name。当注解中有 value 属性时,则给 bean 命名为 value 值。当没有指定名称时,则根据类名自动生成。
- 执行初始化方法。在初始化阶段中我们加载了所有的
ApplicationContextInitializer,依次执行
initializer.initialize(context);
- 发布事件,通知监听者
ApplicationContext已经准备完毕
listeners.contextLoaded(context);
void contextLoaded(ConfigurableApplicationContext context) {
doWithListeners("spring.boot.application.context-loaded", (listener) -> listener.contextLoaded(context));
}
- 将所有的bean加载到容器中
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
- 再次发布事件,通知监听者
ApplicationContext已经装载完毕
listeners.contextLoaded(context);
- 刷新上下文,属于 spring 中的机制,包括了属性自动装配等步骤
refreshContext(context);
- 发布上下文准备就绪事件
listeners.started(context);
879

被折叠的 条评论
为什么被折叠?



