面试基础--Spring Boot启动流程及源码实现

深度解析Spring Boot启动流程及源码实现

一、Spring Boot启动全景图(含核心阶段)

SpringApplication构造 Run方法入口 初始化事件监听器 准备环境配置 创建应用上下文 准备上下文 刷新上下文 执行Runners

二、源码级启动流程拆解

2.1 SpringApplication初始化

java 复制代码
// 源码定位:SpringApplication.java
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

关键操作:

  1. 判定Web应用类型(Servlet/Reactive)
  2. 加载Spring.factories中所有ApplicationContextInitializer
  3. 加载Spring.factories中所有ApplicationListener
  4. 推断主配置类

2.2 Run方法核心流程

java 复制代码
// 源码定位:SpringApplication.java
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
    }
    // 异常处理...
    return context;
}

2.3 环境准备阶段源码解析

java 复制代码
private ConfigurableEnvironment prepareEnvironment(
        SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments) {
    // 创建环境对象
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 配置环境(Profile处理)
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    // 触发EnvironmentPreparedEvent事件
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    return environment;
}

环境处理关键点:

  1. 解析命令行参数(--server.port等)
  2. 加载application.properties/yml
  3. Profile激活处理
  4. 环境变量绑定

三、自动配置实现原理

3.1 @EnableAutoConfiguration处理流程

java 复制代码
// 源码定位:AutoConfigurationImportSelector.class
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
            annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

加载机制:

  1. 从META-INF/spring.factories加载所有配置类
  2. 执行自动配置过滤(@Conditional条件判断)
  3. 按@AutoConfigureOrder排序

3.2 条件注解处理时序

AutoConfiguration类 ConditionEvaluator CFC 检查@Conditional条件 验证类条件 验证Bean条件 验证环境条件 返回是否满足条件 AutoConfiguration类 ConditionEvaluator CFC

四、上下文刷新机制

4.1 AbstractApplicationContext.refresh() 核心流程

java 复制代码
// 源码定位:AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory);
        try {
            postProcessBeanFactory(beanFactory);
            invokeBeanFactoryPostProcessors(beanFactory);
            registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        }
        // 异常处理...
    }
}

关键阶段说明:

  1. BeanFactory后置处理(处理@Configuration)
  2. BeanPostProcessor注册(AOP代理等)
  3. 内嵌Web容器启动(Tomcat/Jetty)
  4. 单例Bean预实例化

五、互联网大厂应用实践

5.1 高频扩展点实践

  1. 自定义EnvironmentPostProcessor
java 复制代码
public class CustomEnvPostProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment env, 
            SpringApplication app) {
        // 动态修改环境配置
    }
}
  1. 自定义FailureAnalyzer
java 复制代码
public class CustomFailureAnalyzer extends AbstractFailureAnalyzer<BeanCreationException> {
    @Override
    protected FailureAnalysis analyze(Throwable rootFailure, 
            BeanCreationException cause) {
        return new FailureAnalysis("自定义错误诊断", "解决方案建议", cause);
    }
}

5.2 启动优化策略

  1. 减少自动配置类扫描
properties 复制代码
spring.autoconfigure.exclude=com.example.unused.config.*
  1. 延迟初始化配置
properties 复制代码
spring.main.lazy-initialization=true
  1. 类加载优化
java 复制代码
@SpringBootApplication
@Configuration(proxyBeanMethods = false)
public class Application { ... }

六、深度调试技巧

  1. 启动时DEBUG参数:
bash 复制代码
java -jar app.jar --debug
  1. 条件评估报告生成:
properties 复制代码
logging.level.org.springframework.boot.autoconfigure=DEBUG
  1. 启动过程Hook注入:
java 复制代码
public static void main(String[] args) {
    new SpringApplicationBuilder(Application.class)
        .addInitializers(new ApplicationContextInitializer(){/*...*/})
        .run(args);
}

七、核心流程图总结

加载SpringFactories配置 创建Environment 准备ApplicationContext 执行BeanFactoryPostProcessor 注册BeanPostProcessor 初始化MessageSource 初始化事件广播器 执行onRefresh 注册监听器 完成Bean初始化 发布ContextRefreshedEvent

本文基于Spring Boot 3.1.0版本源码分析,完整流程图及源码示例已通过内部知识库同步。关注作者获取更多分布式架构深度解析。

相关推荐
洛神灬殇12 分钟前
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 文件事件处理部分)
redis·后端
我真的不会C13 分钟前
Qt中widget控件的常见属性
java·开发语言·qt
左灯右行的爱情13 分钟前
深入学习ReentrantLock
java·后端·juc
gongzairen29 分钟前
Ngrok 内网穿透实现Django+Vue部署
后端·python·django
顾林海30 分钟前
Flutter 图标和按钮组件
android·开发语言·前端·flutter·面试
海姐软件测试35 分钟前
面试求助:在性能测试中发现CPU占用过高应该如何进行分析?
面试·自动化
冒泡的肥皂40 分钟前
JAVA-WEB系统问题排查闲扯
java·spring boot·后端
yuhaiqiang41 分钟前
聊聊我的开源经历——先做个垃圾出来
后端
茂桑1 小时前
Idea集成AI:CodeGeeX开发
java·ai·intellij-idea
杰瑞学AI1 小时前
LeetCode详解之如何一步步优化到最佳解法:27. 移除元素
数据结构·python·算法·leetcode·面试·职场和发展