全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

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加载配置文件
AnsiOutputApplicationListenerANSI 输出配置
EnvironmentPostProcessorApplicationListener环境后处理
SpringApplicationBuilderListenerBuilder 模式支持

自定义 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 是扩展加载的核心机制

📝 发现内容有误?点击此处直接编辑

← 上一篇 Bean 定义加载与注册
下一篇 → Spring Boot 启动流程
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库