Spring Framework 与 Spring Boot 启动对比

Spring Boot 和 Spring Framework 都是构建现代 Java 企业级应用程序的强大工具。Spring Boot 基于 Spring Framework 之上,旨在简化 Spring 应用的创建和配置过程。尽管两者在启动流程上存在许多相似之处,但 Spring Boot 引入了一些额外的机制和约定,以提高开发效率和应用的可扩展性。以下将详细对比两者的启动流程,强调它们的异同点,并结合源码角度进行说明。

目录

  1. 总体架构对比
  2. 启动入口点
  3. 环境准备与配置
  4. 应用上下文创建
  5. Bean 加载与处理
  6. 后处理器与自动配置
  7. Web 服务器的启动
  8. 事件发布与生命周期管理
  9. 总结

1. 总体架构对比

Spring Framework 是一个用于构建 Java 应用程序的全面框架,提供了丰富的功能模块,如依赖注入(DI)、面向切面编程(AOP)、数据访问、事务管理等。

Spring Boot 则是在 Spring Framework 之上提供了一层抽象,旨在简化 Spring 应用的配置和部署。它通过“约定优于配置”(Convention over Configuration)的原则,自动配置应用所需的组件,并提供嵌入式服务器、生产就绪特性(如监控、健康检查)等。

2. 启动入口点

Spring Framework

在 Spring Framework 中,启动应用通常需要手动创建和配置 ApplicationContext。例如,使用 AnnotationConfigApplicationContext

1
2
3
4
5
6
7
8
public class MyApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething();
context.close();
}
}

关键源码:

  • AnnotationConfigApplicationContext 构造函数
    • 注册配置类。
    • 调用 refresh() 方法初始化上下文。

Spring Boot

Spring Boot 使用 SpringApplication.run 方法作为启动入口,通常位于带有 @SpringBootApplication 注解的主类中:

1
2
3
4
5
6
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}

关键源码:

  • SpringApplication.run 方法
    • 创建 SpringApplication 实例。
    • 调用 run 方法执行启动流程。

对比

方面 Spring Framework Spring Boot
启动入口 手动创建 ApplicationContext 使用 SpringApplication.run 方法
配置方式 程序化或 XML 配置 自动配置(Auto-Configuration)
简化程度 需要更多的手动配置和初始化步骤 提供开箱即用的默认配置,减少配置负担

3. 环境准备与配置

Spring Framework

在 Spring Framework 中,环境和属性源的配置通常依赖于手动设置,开发者需要显式地加载属性文件或配置环境:

1
2
3
4
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().getPropertySources().addLast(new ResourcePropertySource("classpath:app.properties"));
context.register(AppConfig.class);
context.refresh();

关键源码:

  • AbstractApplicationContextprepareRefresh 方法
    • 初始化 EnvironmentPropertySources

Spring Boot

Spring Boot 在启动过程中自动准备环境和属性源,支持多种属性加载机制(如命令行参数、环境变量、配置文件等):

  • SpringApplication.prepareEnvironment 方法
    • 创建并配置 Environment 对象。
    • 加载默认的配置属性源,包括 application.propertiesapplication.yml

关键源码:

  • SpringApplication.prepareEnvironment
    • 使用 SpringApplicationRunListeners 触发 EnvironmentPostProcessor 进行环境准备。

对比

方面 Spring Framework Spring Boot
环境配置 手动加载和设置环境属性 自动加载多种属性源(配置文件、命令行等)
属性文件命名 开发者自行决定(如 app.properties 默认使用 application.properties/application.yml
多环境支持 需要手动配置和管理 内置支持多环境配置(如 application-dev.properties

4. 应用上下文创建

Spring Framework

开发者选择特定的 ApplicationContext 实现并手动实例化:

1
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

关键源码:

  • AnnotationConfigApplicationContext 构造函数
    • 注册配置类。
    • 调用 refresh() 初始化上下文。

Spring Boot

Spring Boot 根据应用类型自动选择合适的 ApplicationContext。对于 Web 应用,通常是 AnnotationConfigServletWebServerApplicationContext

关键源码:

  • SpringApplication.createApplicationContext 方法
    • 根据 WebApplicationType 选择上下文类型(NONE, SERVLET, REACTIVE)。
    • 实例化相应的 ApplicationContext 实现。

对比

方面 Spring Framework Spring Boot
上下文选择 开发者手动选择具体的 ApplicationContext 实现 根据应用类型自动选择上下文类型
灵活性 高,开发者可自由选择和定制上下文 简化选择过程,默认选择最适合的上下文

5. Bean 加载与处理

Spring Framework

Bean 的加载主要通过注册配置类或 XML 配置文件,开发者需显式指定:

1
2
3
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();

关键源码:

  • AnnotationConfigApplicationContext.register 方法
    • 注册注解配置类。
  • GenericApplicationContext.refresh 方法
    • 加载和解析 Bean 定义。

Spring Boot

Spring Boot 利用自动配置机制,通过 @EnableAutoConfiguration 注解自动扫描和注册 Bean,无需手动指定配置类:

1
2
3
4
@SpringBootApplication
public class MyApplication {
// ...
}

这里的 @SpringBootApplication 包含了 @EnableAutoConfiguration,它会自动导入配置类。

关键源码:

  • AutoConfigurationImportSelector
    • 通过 spring.factories 文件加载所有自动配置类。
  • ConfigurationClassPostProcessor
    • 处理 @Configuration 类,解析 @Bean@ComponentScan 等注解。

对比

方面 Spring Framework Spring Boot
Bean 定义加载方式 手动注册配置类或 XML 文件 自动扫描和注册,通过自动配置和约定
配置文件依赖 开发者自行组织和管理 依赖 spring.factories 和默认配置类
自动配置支持 无内置自动配置,需要手动集成 内置丰富的自动配置功能,覆盖常见场景

6. 后处理器与自动配置

Spring Framework

在 Spring Framework 中,开发者可以手动注册 BeanFactoryPostProcessorBeanPostProcessor,以定制 Bean 的处理过程:

1
2
context.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
context.addBeanPostProcessor(new MyBeanPostProcessor());

关键源码:

  • AbstractApplicationContext.refresh 方法
    • 调用 invokeBeanFactoryPostProcessorsregisterBeanPostProcessors 方法。

Spring Boot

Spring Boot 自动注册和配置多个 BeanFactoryPostProcessorBeanPostProcessor,以实现自动配置和额外功能:

  • 自动配置类:通过 @Configuration 类和条件注解(如 @ConditionalOnMissingBean)实现灵活的配置。
  • 内置后处理器:如 ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessor 等,自动处理 Bean 的注入和配置。

关键源码:

  • SpringApplication.invokeBeanFactoryPostProcessors 方法
    • 加载并执行所有 BeanFactoryPostProcessor,包括自动配置相关的处理器。
  • **AutoConfigurationImportSelector**:选择并导入自动配置类。

对比

方面 Spring Framework Spring Boot
后处理器注册 手动注册或通过配置文件 自动注册内置和自动配置相关的后处理器
自动配置机制 不存在,需开发者手动集成 内置丰富的自动配置机制,通过条件注解实现
拓展性 高,开发者可自由添加和定制后处理器 支持自定义自动配置,但受限于 Spring Boot 的机制

7. Web 服务器的启动

Spring Framework

在 Spring Framework 中,作为 Web 应用时,通常需要配置和部署到外部的 Servlet 容器(如 Tomcat、Jetty)。启动过程主要涉及:

  • 配置 DispatcherServlet
  • 部署到外部服务器中运行。
1
2
3
4
5
6
<!-- web.xml 示例 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

Spring Boot

Spring Boot 提供了嵌入式的 Web 服务器(如 Tomcat、Jetty、Undertow),无需外部部署。启动时自动初始化并启动嵌入式服务器:

1
2
3
4
5
6
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}

关键源码:

  • SpringApplication.run 方法

    • 检测应用类型(Web 或非 Web)。
    • 创建 WebServer(如 Tomcat)并启动。
  • ServletWebServerApplicationContext

    • 管理嵌入式服务器的生命周期。

对比

方面 Spring Framework Spring Boot
Web 服务器部署方式 需要外部 Servlet 容器进行部署 内置嵌入式服务器,无需外部容器
配置复杂度 较高,需要手动配置和集成外部服务器 简化配置,自动集成和启动嵌入式服务器
灵活性 开发者需自行管理服务器的配置和生命周期 自动管理服务器生命周期,开发者可通过配置调整

8. 事件发布与生命周期管理

Spring Framework

在 Spring Framework 中,事件发布和生命周期管理主要通过 ApplicationEventPublisherLifecycle 接口实现。开发者需要手动注册监听器和处理生命周期事件:

1
2
3
4
5
6
7
8
context.publishEvent(new CustomEvent(this));

public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
// 处理事件
}
}

Spring Boot

Spring Boot 在 Spring Framework 的基础上,进一步简化和扩展了事件发布和生命周期管理:

  • 内置事件监听器:如 ApplicationRunnerCommandLineRunner,用于在应用启动后执行特定逻辑。
  • 自动触发事件:如 ContextRefreshedEventApplicationReadyEvent,提供更多生命周期内的钩子。
  • 集成生产就绪特性:通过 Actuator 提供健康检查、指标监控等功能。

关键源码:

  • SpringApplication.callRunners 方法
    • 调用所有实现了 CommandLineRunnerApplicationRunner 的 Bean。
  • SpringApplication.finishRefresh 方法
    • 发布 ContextRefreshedEventApplicationReadyEvent

对比

方面 Spring Framework Spring Boot
事件发布 基于 ApplicationEventPublisher,需手动发布事件 自动发布多个生命周期事件,支持更多钩子
生命周期回调 需要手动实现和注册监听器 提供内置接口(如 CommandLineRunner)和默认监听器
生产就绪特性 不内置,需要开发者自行集成和实现 内置丰富的生产就绪特性,通过 Actuator 提供

9. 总结

Spring Boot 和 Spring Framework 在启动流程上有许多共同点,主要基于 Spring Framework 的核心机制。然而,Spring Boot 通过自动配置、嵌入式服务器、简化的启动入口等功能,显著简化了应用的配置和部署过程。以下是两者的关键异同点总结:

相似点

  • 基于 Spring 核心:两者都利用 Spring Framework 的核心功能,如 IoC 容器、依赖注入、AOP 等。
  • 应用上下文:都使用 ApplicationContext 作为 IoC 容器,负责管理 Bean 的生命周期。
  • 事件机制:基于相同的事件发布与监听机制,支持应用生命周期事件的处理。
  • Bean 加载与后处理:使用类似的 Bean 定义加载和后处理机制,通过 BeanFactoryPostProcessorBeanPostProcessor 扩展功能。

不同点

方面 Spring Framework Spring Boot
启动方式 手动创建和配置 ApplicationContext 使用 SpringApplication.run 简化启动
配置复杂度 需要手动配置和管理多个组件 提供自动配置,减少手动配置需求
Web 服务器部署方式 依赖外部 Servlet 容器进行部署 内置嵌入式服务器,简化部署流程
自动配置支持 无内置自动配置机制,需手动集成各类组件 内置丰富的自动配置,通过约定简化配置
生产就绪特性 需要手动集成和实现 提供 Actuator 等内置生产就绪功能
依赖管理 开发者需自行管理和配置依赖关系 提供 Starters 统一管理依赖,简化依赖配置

结论

Spring Boot 是对 Spring Framework 的重大扩展,旨在简化和加速 Spring 应用的开发过程。通过自动配置、嵌入式服务器、生产就绪特性等功能,Spring Boot 帮助开发者更高效地构建和部署应用,而无需深入处理底层的配置细节。然而,Spring Boot 仍然保留了 Spring Framework 的核心灵活性和扩展性,使其在需要时能够进行高度自定义和优化。理解两者的启动流程和工作机制,有助于开发者在不同场景下选择合适的工具和策略,构建高效、可维护的企业级应用程序。