Skip to content
章节导航

SpringBoot 工程的启动步骤

java
// 1. 启动入口
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
      // 这是启动的起点
      SpringApplication.run(Application.class, args);
    }
}

完整启动流程图

  • 1、启动入口:SpringApplication.run()
  • 2、实例化 SpringApplication 对象
  • 3、执行 run() 方法
  • 4、SpringApplicationRunListeners 开始监听
  • 5、准备 Environment
  • 6、打印 Banner
  • 7、创建 ApplicationContext
  • 8、准备 ApplicationContext
  • 9、刷新 ApplicationContext(核心!)
  • 10、调用 ApplicationRunner/CommandLineRunner
  • 11、应用启动完成

详细启动步骤分析

1、启动入口阶段

java
// 1. 启动入口
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 这是启动的起点
        SpringApplication.run(Application.class, args);
    }
}

// SpringApplication.run() 方法的内部调用链
public class SpringApplication {
    
    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class<?>[]{primarySource}, args);
    }
    
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        // 创建 SpringApplication 实例
        return new SpringApplication(primarySources).run(args);
    }
}

2、SpringApplication 实例化

java
public class SpringApplication {
    
    public SpringApplication(Class<?>... primarySources) {
        this(null, primarySources);
    }
    
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        // 1. 设置 primarySources(主配置类)
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        
        // 2. 推断 Web 应用类型
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        
        // 3. 设置 ApplicationContextInitializer
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        
        // 4. 设置 ApplicationListener
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        
        // 5. 推断主应用类
        this.mainApplicationClass = deduceMainApplicationClass();
    }
    
    // 推断 Web 应用类型
    private WebApplicationType deduceFromClasspath() {
        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", null) 
            && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null) 
            && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", null)) {
            return WebApplicationType.REACTIVE;  // WebFlux 应用
        }
        for (String className : SERVLET_INDICATOR_CLASSES) {
            if (!ClassUtils.isPresent(className, null)) {
                return WebApplicationType.NONE;  // 非 Web 应用
            }
        }
        return WebApplicationType.SERVLET;  // Servlet Web 应用
    }
    
    
    public ConfigurableApplicationContext run(String... args) {
        // .....
    }
}

3、运行阶段(run() 方法)

java
public class SpringApplication {
    
    public ConfigurableApplicationContext run(String... args) {
        // 1. 创建启动计时器
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        // 2. 创建引导上下文(Spring Boot 2.4+)
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        
        // 3. 配置 headless 模式
        configureHeadlessProperty();
        
        // 4. 获取 SpringApplicationRunListeners
        SpringApplicationRunListeners listeners = getRunListeners(args);
        
        // 5. 发布 ApplicationStartingEvent
        listeners.starting();
        
        try {
            // 6. 准备 ApplicationArguments
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            
            // 7. 准备 Environment
            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            
            // 8. 配置忽略的 Bean
            configureIgnoreBeanInfo(environment);
            
            // 9. 打印 Banner
            Banner printedBanner = printBanner(environment);
            
            // 10. 创建 ApplicationContext
            context = createApplicationContext();
            
            // 11. 准备异常报告器
            exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, 
                context
            );
            
            // 12. 准备 ApplicationContext
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            
            // 13. 刷新 ApplicationContext(核心!)
            refreshContext(context);
            
            // 14. 刷新后的处理
            afterRefresh(context, applicationArguments);
            
            // 15. 停止计时器
            stopWatch.stop();
            
            // 16. 发布 ApplicationStartedEvent
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                    .logStarted(getApplicationLog(), stopWatch);
            }
            listeners.started(context);
            
            // 17. 调用 Runner
            callRunners(context, applicationArguments);
            
            // 18. 发布 ApplicationReadyEvent
            listeners.ready(context);
            
        } catch (Throwable ex) {
            // 处理启动异常
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }
        
        return context;
    }
}

4、环境准备阶段

java
private ConfigurableEnvironment prepareEnvironment(
        SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments) {
    
    // 1. 创建 Environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    
    // 2. 配置 Environment
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    
    // 3. 发布 ApplicationEnvironmentPreparedEvent
    listeners.environmentPrepared(environment);
    
    // 4. 绑定 Environment 到 SpringApplication
    bindToSpringApplication(environment);
    
    // 5. 转换环境(如果不是 CustomEnvironment)
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader())
            .convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    
    // 6. 配置 PropertySources
    ConfigurationPropertySources.attach(environment);
    
    return environment;
}

// 创建合适的 Environment
private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    }
    
    switch (this.webApplicationType) {
        case SERVLET:
            return new StandardServletEnvironment();
        case REACTIVE:
            return new StandardReactiveWebEnvironment();
        default:
            return new StandardEnvironment();
    }
}

5、创建 ApplicationContext

java
protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    
    if (contextClass == null) {
        try {
            // 根据 Web 应用类型选择 Context 类
            switch (this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                    break;
                case REACTIVE:
                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                    break;
                default:
                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
            }
        } catch (ClassNotFoundException ex) {
            throw new IllegalStateException("Unable create a default ApplicationContext", ex);
        }
    }
    
    // 使用反射创建 ApplicationContext 实例
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

// 默认的 ApplicationContext 类:
// Servlet Web: AnnotationConfigServletWebServerApplicationContext
// Reactive Web: AnnotationConfigReactiveWebServerApplicationContext
// 非 Web: AnnotationConfigApplicationContext

6、准备 ApplicationContext

java
private void prepareContext(ConfigurableApplicationContext context,
        ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments, Banner printedBanner) {
    
    // 1. 设置 Environment
    context.setEnvironment(environment);
    
    // 2. 后处理 ApplicationContext
    postProcessApplicationContext(context);
    
    // 3. 应用 ApplicationContextInitializer
    applyInitializers(context);
    
    // 4. 发布 ApplicationContextInitializedEvent
    listeners.contextPrepared(context);
    
    // 5. 打印启动信息
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    
    // 6. 获取 BeanFactory
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    
    // 7. 注册单例 Bean
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    
    // 8. 设置允许 Bean 定义覆盖
    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    
    // 9. 设置懒加载
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    
    // 10. 加载 Bean 定义
    load(context, sources.toArray(new Object[0]));
    
    // 11. 发布 ApplicationPreparedEvent
    listeners.contextLoaded(context);
}

7、刷新 ApplicationContext(核心!)

java
// AbstractApplicationContext.refresh() - Spring 容器的核心生命周期
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备刷新
        prepareRefresh();
        
        // 2. 获取新的 BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
        // 3. 准备 BeanFactory
        prepareBeanFactory(beanFactory);
        
        try {
            // 4. 后处理 BeanFactory
            postProcessBeanFactory(beanFactory);
            
            // 5. 调用 BeanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactory);
            
            // 6. 注册 BeanPostProcessor
            registerBeanPostProcessors(beanFactory);
            
            // 7. 初始化消息源
            initMessageSource();
            
            // 8. 初始化事件广播器
            initApplicationEventMulticaster();
            
            // 9. 初始化特殊 Bean(由子类实现)
            onRefresh();
            
            // 10. 注册监听器
            registerListeners();
            
            // 11. 完成 BeanFactory 初始化
            finishBeanFactoryInitialization(beanFactory);
            
            // 12. 完成刷新
            finishRefresh();
            
        } catch (BeansException ex) {
            // 13. 销毁已经创建的单例 Bean
            destroyBeans();
            
            // 14. 取消刷新
            cancelRefresh(ex);
            
            throw ex;
        } finally {
            // 15. 重置公共缓存
            resetCommonCaches();
        }
    }
}

refresh() 方法的详细步骤

java
// 步骤1:准备刷新
protected void prepareRefresh() {
    // 1.1 设置启动时间和活跃状态
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    
    // 1.2 初始化属性源
    initPropertySources();
    
    // 1.3 验证必需属性
    getEnvironment().validateRequiredProperties();
    
    // 1.4 存储早期应用事件
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

// 步骤2:获取 BeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 2.1 刷新 BeanFactory
    refreshBeanFactory();
    
    // 2.2 获取 BeanFactory
    return getBeanFactory();
}

// 步骤5:调用 BeanFactoryPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 这是自动装配的关键步骤!
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    
    // 5.1 处理 BeanDefinitionRegistryPostProcessor(如 ConfigurationClassPostProcessor)
    // 5.2 处理 BeanFactoryPostProcessor
    // 5.3 处理 ImportBeanDefinitionRegistrar
}

// 步骤9:onRefresh() - 由子类实现
protected void onRefresh() throws BeansException {
    // 对于 Web 应用,这里会创建 WebServer
    // ServletWebServerApplicationContext 会在这里创建并启动 Tomcat/Jetty/Undertow
}

// 步骤11:完成 BeanFactory 初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 11.1 初始化 ConversionService
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)) {
        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class);
    }
    
    // 11.2 注册默认的嵌入值解析器
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    
    // 11.3 尽早初始化 LoadTimeWeaverAware Bean
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    
    // 11.4 停止使用临时类加载器
    beanFactory.setTempClassLoader(null);
    
    // 11.5 缓存所有 Bean 定义元数据
    beanFactory.freezeConfiguration();
    
    // 11.6 实例化所有剩余的单例 Bean(核心!)
    beanFactory.preInstantiateSingletons();
}

8、调用 Runner

java
private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList<>();
    
    // 1. 获取所有 ApplicationRunner
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    
    // 2. 获取所有 CommandLineRunner  
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    
    // 3. 排序(使用 @Order 注解)
    AnnotationAwareOrderComparator.sort(runners);
    
    // 4. 调用所有 Runner
    for (Object runner : new LinkedHashSet<>(runners)) {
        if (runner instanceof ApplicationRunner) {
            callRunner((ApplicationRunner) runner, args);
        }
        if (runner instanceof CommandLineRunner) {
            callRunner((CommandLineRunner) runner, args);
        }
    }
}

private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
    try {
        runner.run(args);
    } catch (Exception ex) {
        throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
    }
}

关键扩展点分析

1、ApplicationContextInitializer

在 ApplicationContext 刷新之前进行自定义初始化

java
public class CustomApplicationContextInitializer 
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("【ApplicationContextInitializer】自定义初始化");
        
        // 1. 设置环境属性
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        environment.getPropertySources().addFirst(new MyPropertySource());
        
        // 2. 注册自定义 Bean
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext;
        registry.registerBeanDefinition("customBean", 
            BeanDefinitionBuilder.genericBeanDefinition(CustomBean.class).getBeanDefinition());
        
        // 3. 修改 BeanFactory 配置
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        beanFactory.addBeanPostProcessor(new CustomBeanPostProcessor());
    }
}

// 注册方式:
// 1. 在 META-INF/spring.factories 中:
// org.springframework.context.ApplicationContextInitializer=com.example.CustomApplicationContextInitializer
// 
// 2. 通过 SpringApplication.addInitializers() 添加

2、ApplicationListener

监听 Spring Boot 启动事件

java
@Component
public class CustomApplicationListener implements ApplicationListener<ApplicationEvent> {
    
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        // 监听所有应用事件
        if (event instanceof ApplicationStartingEvent) {
            System.out.println("【事件】应用开始启动");
        } else if (event instanceof ApplicationEnvironmentPreparedEvent) {
            System.out.println("【事件】环境准备完成");
        } else if (event instanceof ApplicationContextInitializedEvent) {
            System.out.println("【事件】ApplicationContext 初始化完成");
        } else if (event instanceof ApplicationPreparedEvent) {
            System.out.println("【事件】ApplicationContext 准备完成");
        } else if (event instanceof ApplicationStartedEvent) {
            System.out.println("【事件】应用启动完成");
        } else if (event instanceof ApplicationReadyEvent) {
            System.out.println("【事件】应用准备就绪,可以接收请求");
        } else if (event instanceof ApplicationFailedEvent) {
            System.out.println("【事件】应用启动失败");
        }
    }
}

特定事件监听器

java
@Component
public class EnvironmentPreparedListener 
        implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
    
    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        ConfigurableEnvironment environment = event.getEnvironment();
        SpringApplication application = event.getSpringApplication();
        
        // 可以在这里修改环境配置
        Map<String, Object> defaultProperties = new HashMap<>();
        defaultProperties.put("custom.property", "value");
        application.setDefaultProperties(defaultProperties);
    }
}

3、BeanFactoryPostProcessor

在 BeanFactory 准备完成后,Bean 实例化之前修改 Bean 定义

java
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
            throws BeansException {
        System.out.println("【BeanFactoryPostProcessor】处理 BeanFactory");
        
        // 1. 获取所有 Bean 定义
        String[] beanNames = beanFactory.getBeanDefinitionNames();
        
        for (String beanName : beanNames) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            
            // 2. 修改 Bean 定义
            if (beanDefinition.getBeanClassName() != null && 
                beanDefinition.getBeanClassName().contains("Service")) {
                // 修改 Service 类的作用域
                beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
                
                // 添加属性值
                MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
                propertyValues.add("customProperty", "customValue");
            }
            
            // 3. 注册新的 Bean 定义
            if (beanFactory instanceof BeanDefinitionRegistry) {
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
                if (!registry.containsBeanDefinition("customBean")) {
                    BeanDefinitionBuilder builder = BeanDefinitionBuilder
                        .genericBeanDefinition(CustomBean.class);
                    registry.registerBeanDefinition("customBean", builder.getBeanDefinition());
                }
            }
        }
    }
}

4、BeanPostProcessor

在 Bean 初始化前后进行处理

java
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
            throws BeansException {
        // Bean 初始化之前调用
        if (bean instanceof InitializingBean) {
            System.out.println("【BeanPostProcessor】Bean 初始化前: " + beanName);
        }
        
        // 可以返回包装后的 Bean
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) 
            throws BeansException {
        // Bean 初始化之后调用
        if (bean instanceof Aware) {
            System.out.println("【BeanPostProcessor】Bean 初始化后: " + beanName);
        }
        
        // AOP 代理通常在这里创建
        if (bean.getClass().isAnnotationPresent(Transactional.class)) {
            // 创建事务代理
            return createTransactionProxy(bean);
        }
        
        return bean;
    }
}

性能优化点

1、启动性能优化配置

java
@SpringBootApplication
public class Application {
    
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        
        // 1. 延迟初始化(Spring Boot 2.2+)
        app.setLazyInitialization(true);
        
        // 2. 排除不需要的自动配置
        app.setBannerMode(Banner.Mode.OFF);
        
        // 3. 设置特定的 Web 应用类型
        app.setWebApplicationType(WebApplicationType.SERVLET);
        
        // 4. 优化日志级别
        System.setProperty("logging.level.root", "WARN");
        System.setProperty("logging.level.org.springframework", "WARN");
        
        app.run(args);
    }
}

2、配置优化

java
@Configuration
public class StartupOptimizationConfig {
    
    // 1. 使用 @Configuration(proxyBeanMethods = false)
    @Configuration(proxyBeanMethods = false)  // 避免 CGLIB 代理
    public static class OptimizedConfig {
        // 配置类
    }
    
    // 2. 懒加载 Bean
    @Bean
    @Lazy
    public ExpensiveBean expensiveBean() {
        return new ExpensiveBean();
    }
    
    // 3. 排除不必要的扫描
    @ComponentScan(
        excludeFilters = @ComponentScan.Filter(
            type = FilterType.REGEX,
            pattern = "com.example.exclude.*"
        )
    )
    public static class SelectiveScanConfig {
        // 选择性扫描
    }
}