SpringApplication 初始化
SpringApplication 构造阶段完成启动前的准备工作,推断应用类型并加载核心组件。
SpringApplication 构造
构造方法核心
Java
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 1. 推断 Web 应用类型
this.webApplicationType = deduceWebApplicationType();
// 2. 加载 Bootstrap Registry Initializer
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializers();
// 3. 加载 ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 4. 加载 ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 5. 推断主类
this.mainApplicationClass = deduceMainApplicationClass();
}
主类推断
deduceMainApplicationClass()
Java
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement element : stackTrace) {
if ("main".equals(element.getMethodName())) {
return Class.forName(element.getClassName());
}
}
} catch (ClassNotFoundException ex) {
// 无法推断时忽略
}
return null;
}
推断原理
- 通过堆栈追踪找到 main 方法
- main 方法所在类即为启动主类
- 用于日志输出和启动报告
Web 应用类型推断
deduceWebApplicationType()
Java
private WebApplicationType deduceWebApplicationType() {
// 检查 Reactive 环境
if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
&& !ClassUtils.isPresent(SERVLET_WEB_ENVIRONMENT_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
// 检查 Servlet 环境
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
类型判断依据
| 类型 | 判断条件 |
|---|---|
| REACTIVE | 存在 DispatcherHandler,不存在 DispatcherServlet |
| SERVLET | 存在 DispatcherServlet 和 ServletRequest |
| NONE | 以上类都不存在 |
WebApplicationType 枚举
Java
public enum WebApplicationType {
NONE, // 非 Web 应用
SERVLET, // Servlet Web 应用
REACTIVE // Reactive Web 应用
}
加载 Initializer
getSpringFactoriesInstances()
Java
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 使用 SpringFactoriesLoader 加载
Set<String> names = SpringFactoriesLoader.loadFactoryNames(type, classLoader);
// 创建实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
SpringFactoriesLoader
Java
public static List<String> loadFactoryNames(Class<?> factoryType, ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
// 从 spring.factories 加载
Map<String, List<String>> properties = loadSpringFactories(classLoader);
return properties.getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
// 从 META-INF/spring.factories 读取
Enumeration<URL> urls = classLoader.getResources("META-INF/spring.factories");
// 解析并缓存
}
spring.factories 示例
properties
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer
org.springframework.boot.ApplicationListener=\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener
ApplicationContextInitializer
内置 Initializer
| Initializer | 作用 |
|---|---|
| ConfigurationWarningsApplicationContextInitializer | 检查配置警告 |
| ContextIdApplicationContextInitializer | 设置上下文 ID |
| DelegatingApplicationContextInitializer | 代理其他 Initializer |
| EnvironmentPostProcessorApplicationContextInitializer | 执行环境后处理 |
| SharedMetadataReaderFactoryContextInitializer | 共享元数据读取器 |
自定义 Initializer
Java
public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
// 上下文初始化前执行
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.getSystemProperties().put("app.initialized", "true");
}
}
注册 Initializer
properties
# spring.factories
org.springframework.context.ApplicationContextInitializer=com.example.MyApplicationContextInitializer
ApplicationListener
内置 Listener
| Listener | 作用 |
|---|---|
| LoggingApplicationListener | 初始化日志系统 |
| ConfigFileApplicationListener | 加载配置文件 |
| AnsiOutputApplicationListener | ANSI 输出配置 |
| EnvironmentPostProcessorApplicationListener | 环境后处理 |
| SpringApplicationBuilderListener | Builder 模式支持 |
自定义 Listener
Java
public class MyApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
// 环境准备后执行
}
}
BootstrapRegistryInitializer
Bootstrap 上下文初始化
Java
// Spring Boot 2.4+ 新增
public interface BootstrapRegistryInitializer {
void initialize(BootstrapRegistry registry);
}
// 注册 Bootstrap Bean(在 ApplicationContext 创建前)
registry.register(SomeBean.class, context -> new SomeBean());
ResourceLoader 设置
类加载器配置
Java
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
// 获取类加载器
this.classLoader = resourceLoader != null ? resourceLoader.getClassLoader() : null;
}
public ClassLoader getClassLoader() {
return this.resourceLoader != null ? this.resourceLoader.getClassLoader()
: ClassUtils.getDefaultClassLoader();
}
注意:spring.factories 加载机制是 Spring Boot 扩展的核心,所有自动配置和监听器都通过此机制加载。
要点总结
- 主类推断通过堆栈追踪实现
- WebApplicationType 决定容器类型
- ApplicationContextInitializer 在上下文创建前执行
- ApplicationListener 监听启动事件
- spring.factories 是扩展加载的核心机制
📝 发现内容有误?点击此处直接编辑