1. 学习目标

通过本章学习,你将能够:

  • 理解 Spring 框架的诞生背景、核心设计理念与生态体系
  • 掌握 Spring Framework 6.x 的核心升级特性及其对开发的影响
  • 独立搭建基于 JDK 21 + Maven + IntelliJ IDEA 的 Spring 开发环境
  • 创建并运行第一个基于全注解配置的 Spring 程序

2. 核心概念

2.1 Spring 框架的诞生与发展历程

2002 年,Rod Johnson 在《Expert One-on-One J2EE Design and Development》一书中,首次质疑了当时 EJB(Enterprise JavaBeans)的复杂性和重量级设计。他指出,企业级 Java 开发并不需要 EJB 的繁重容器,使用普通的 Java 对象(POJO)配合轻量级依赖注入,就能构建出同样强大的企业应用。

2003 年,Rod Johnson 与 Juergen Hoeller 等人基于书中的理念,正式发布了 Spring Framework 1.0。Spring 的核心理念可以概括为:

“让 Java 开发变得更简单” —— 通过 IOC(控制反转)和 AOP(面向切面编程)两大核心技术,Spring 将开发者从复杂的 EJB 容器、JNDI 查找、冗长的 XML 配置中解放出来。

Spring 版本演进的关键节点:

版本 发布时间 里程碑特性
Spring 1.0 2004.03 IoC 容器、AOP 支持、JDBC 模板
Spring 2.0 2006.10 XML Schema 配置、注解支持、AspectJ 集成
Spring 2.5 2007.11 @Autowired、@Component 注解驱动开发
Spring 3.0 2009.12 JavaConfig、@Configuration、SpEL 表达式
Spring 4.0 2013.12 Java 8 全面支持、@RestController、WebSocket
Spring 5.0 2017.09 响应式编程(WebFlux)、Java 9+ 支持
Spring 6.0 2022.11 Java 17+ 基线、Jakarta EE 9+、AOT 编译、虚拟线程预备
Spring 6.2 2024.11 @Fallback Bean、后台初始化、AssertJ 集成、SpEL 增强

2.2 Spring 生态体系全景图

Spring 早已不只是一个框架,而是一个庞大的生态系统。理解这个全景图,才能知道在什么场景下使用什么组件:

┌─────────────────────────────────────────────────────────────┐
│                    Spring 生态全景图                          │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │  Spring Boot │  │ Spring Cloud │  │ Spring AI    │       │
│  │  快速开发     │  │  微服务治理   │  │  AI 集成     │       │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘       │
│         │                 │                 │                │
│  ┌──────┴─────────────────┴─────────────────┴───────┐       │
│  │            Spring Framework 核心                   │       │
│  │  IoC Container · AOP · Beans · Context · SpEL    │       │
│  └──────┬───────────────────────────────────────────┘       │
│         │                                                    │
│  ┌──────┴───────────────────────────────────────────┐       │
│  │ Spring Data (JPA · JDBC · Redis · MongoDB · ...) │       │
│  │ Spring Security (认证 · 授权 · OAuth2)            │       │
│  │ Spring MVC / WebFlux (Web 开发)                  │       │
│  │ Spring Batch (批处理) · Spring Integration (集成)  │       │
│  └──────────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────────┘

Spring Framework:整个生态的基石,提供 IoC 容器、AOP、数据访问等核心能力。

Spring Boot:在 Framework 之上,通过"约定优于配置"和自动配置,让开发者可以快速创建独立运行的生产级应用。Spring Boot 不是替代 Spring Framework,而是对它的封装和增强。

Spring Cloud:基于 Spring Boot 构建的微服务解决方案,提供服务发现、配置中心、网关、熔断等分布式系统能力。

Spring Data:数据访问层抽象,统一了关系型数据库(JPA/JDBC)、NoSQL(Redis/MongoDB)、搜索引擎(Elasticsearch)的访问方式。

Spring Security:认证和授权框架,是 Java 生态中最强大的安全框架。

Spring AI(2024 年新项目):将 AI 能力集成到 Spring 应用中,支持向量数据库、提示工程、工具调用等。

2.3 Spring Framework 6.x 核心升级特性

Spring 6.x 是一次跨越式的版本升级,以下是必须了解的核心变化:

2.3.1 Java 17+ 基线要求

Spring 6.x 最低要求 Java 17,这意味着:

  • 可以使用 RecordsSealed ClassesPattern MatchingText Blocks 等现代 Java 特性
  • 不再兼容 Java 8/11,老项目迁移需要升级 JDK
// Java 17 Record 类在 Spring 中的使用
public record UserDTO(Long id, String name, String email) {
    // 紧凑构造器进行校验
    public UserDTO {
        if (name == null || name.isBlank()) {
            throw new IllegalArgumentException("name 不能为空");
        }
    }
}
2.3.2 Jakarta EE 9+ 命名空间迁移

最大 Breaking Change:javax.* 全部迁移到 jakarta.*

// Spring 5.x (旧)
import javax.servlet.http.HttpServlet;
import javax.persistence.Entity;
import javax.annotation.PostConstruct;

// Spring 6.x (新)
import jakarta.servlet.http.HttpServlet;
import jakarta.persistence.Entity;
import jakarta.annotation.PostConstruct;

如果你使用的是 Spring Boot 3.x,它会自动处理这个迁移。但如果你的项目中有直接依赖 javax.* 的第三方库,需要升级或替换。

2.3.3 AOT 编译与原生镜像

AOT(Ahead-Of-Time)编译允许在构建时预处理 Spring 的反射、代理等动态行为,使应用可以编译为 GraalVM 原生镜像:

  • 启动速度:从秒级降到毫秒级(< 100ms)
  • 内存占用:减少 50-70%
  • 适用场景:Serverless、容器化部署、微服务
2.3.4 虚拟线程(Virtual Threads)

Spring 6.1+ 支持 Java 21 的虚拟线程,在高并发场景下大幅提升吞吐量:

@Configuration
public class VirtualThreadConfig {
    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
    }
}
2.3.5 @Fallback Bean(Spring 6.2 新增)

当主 Bean 不可用时,自动切换到备选 Bean:

@Configuration
public class FallbackConfig {
    @Bean
    public PaymentService primaryPaymentService() {
        return new AlipayService();  // 主支付服务
    }

    @Bean
    @Fallback
    public PaymentService fallbackPaymentService() {
        return new WechatPayService();  // 备选支付服务
    }
}

2.4 Spring 模块化架构深入解析

Spring Framework 本身由约 20 个模块组成,按功能分为六组:

核心容器(Core Container)
  • spring-core:框架的基础工具类,包括反射、IO、类型转换等
  • spring-beans:Bean 的创建、管理和依赖注入,BeanFactory 接口
  • spring-context:ApplicationContext,在 BeanFactory 之上增加了国际化、事件传播、资源加载等
  • spring-expression:SpEL(Spring Expression Language)表达式语言
AOP 与 Instrumentation
  • spring-aop:基于代理的 AOP 实现
  • spring-aspects:与 AspectJ 的集成
  • spring-instrument:类加载时织入支持
数据访问(Data Access)
  • spring-jdbc:JDBC 抽象层,JdbcTemplate
  • spring-orm:ORM 框架集成(Hibernate、JPA)
  • spring-tx:声明式和编程式事务管理
  • spring-jms:JMS 消息集成
Web 层
  • spring-web:基础的 Web 功能(文件上传、Web 工具类)
  • spring-webmvc:Spring MVC 框架
  • spring-webflux:响应式 Web 框架
  • spring-websocket:WebSocket 支持
测试
  • spring-test:集成测试支持(JUnit/Mockito 集成)

2.5 开发环境搭建

2.5.1 安装 JDK 21
# macOS 使用 Homebrew 安装
brew install openjdk@21

# 验证安装
java -version
# 输出:openjdk version "21.0.x" ...

# 配置环境变量(~/.zshrc)
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
export PATH="$JAVA_HOME/bin:$PATH"
2.5.2 安装 Maven
# macOS 安装
brew install maven

# 验证
mvn -v
# 输出:Apache Maven 3.9.x ...
2.5.3 Maven 配置优化

编辑 ~/.m2/settings.xml

<settings>
    <!-- 阿里云镜像加速 -->
    <mirrors>
        <mirror>
            <id>aliyun</id>
            <mirrorOf>central</mirrorOf>
            <name>Aliyun Maven Mirror</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </mirror>
    </mirrors>
    
    <!-- JDK 21 编译配置 -->
    <profiles>
        <profile>
            <id>jdk21</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <maven.compiler.source>21</maven.compiler.source>
                <maven.compiler.target>21</maven.compiler.target>
                <maven.compiler.compilerVersion>21</maven.compiler.compilerVersion>
            </properties>
        </profile>
    </profiles>
</settings>

2.6 第一个 Spring 程序:Hello World 全注解版

2.6.1 创建 Maven 项目
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>spring-hello</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <java.version>21</java.version>
        <spring.version>6.2.19</spring.version>
    </properties>

    <dependencies>
        <!-- Spring Context(包含 beans, core, expression, aop) -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
2.6.2 编写业务类
// src/main/java/com/example/service/MessageService.java
package com.example.service;

import org.springframework.stereotype.Service;

@Service  // 标记为 Spring Bean
public class MessageService {

    public String getMessage() {
        return "Hello, Spring 6!";
    }
}
// src/main/java/com/example/controller/MessageController.java
package com.example.controller;

import com.example.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component  // 标记为 Spring 管理的组件
public class MessageController {

    private final MessageService messageService;

    // 构造器注入(推荐方式)
    @Autowired
    public MessageController(MessageService messageService) {
        this.messageService = messageService;
    }

    public void printMessage() {
        System.out.println(messageService.getMessage());
    }
}
2.6.3 配置类
// src/main/java/com/example/config/AppConfig.java
package com.example.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration            // 标记为配置类
@ComponentScan("com.example")  // 扫描 com.example 包下的所有组件
public class AppConfig {
    // 配置类本身不需要写代码,注解已经完成了所有配置
}
2.6.4 启动类
// src/main/java/com/example/MainApplication.java
package com.example;

import com.example.config.AppConfig;
import com.example.controller.MessageController;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApplication {

    public static void main(String[] args) {
        // 1. 创建 IoC 容器(基于注解配置)
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AppConfig.class);

        // 2. 从容器中获取 Bean
        MessageController controller = context.getBean(MessageController.class);

        // 3. 使用 Bean
        controller.printMessage();
        // 输出:Hello, Spring 6!

        // 4. 关闭容器
        context.close();
    }
}
2.6.5 运行与验证
# 编译
mvn clean compile

# 运行
mvn exec:java -Dexec.mainClass="com.example.MainApplication"

# 输出:
# Hello, Spring 6!

2.7 程序启动流程分析

上面的代码背后发生了什么?让我们跟踪 Spring 容器启动的关键步骤:

1. AnnotationConfigApplicationContext(AppConfig.class)
   └── 创建 IoC 容器实例

2. 容器读取 AppConfig 配置类
   └── @Configuration 标记这是一个配置类
   └── @ComponentScan("com.example") 触发包扫描

3. 包扫描过程
   └── 扫描 com.example 包及子包下的所有 .class 文件
   └── 发现 @Service 标记的 MessageService
   └── 发现 @Component 标记的 MessageController
   └── 为每个组件创建 BeanDefinition(Bean 的定义信息)

4. 实例化 Bean
   └── 创建 MessageService 实例(无依赖,直接实例化)
   └── 创建 MessageController 实例
   └── 发现构造器上有 @Autowired,注入 MessageService 实例

5. 容器初始化完成
   └── 所有单例 Bean 创建完毕,等待使用

6. context.getBean(MessageController.class)
   └── 从容器缓存中取出已创建好的 MessageController 实例

7. context.close()
   └── 销毁所有单例 Bean,释放资源

3. 常见陷阱

陷阱1:组件扫描路径不正确

// 错误:扫描路径写错了
@ComponentScan("com.exmaple")  // 拼写错误

// 正确:确保扫描路径覆盖所有组件所在的包
@ComponentScan("com.example")

陷阱2:忘记添加 @Component 或其派生注解

// 错误:MessageService 没有被 Spring 管理
public class MessageService { }  // 不会被扫描到!

// 正确:添加 @Service 注解
@Service
public class MessageService { }

陷阱3:Maven 依赖版本不兼容

<!-- 错误:混用 Spring 5.x 和 6.x 的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.30</version>  <!-- 这是 Spring 5,运行在 Java 8+ -->
</dependency>

4. 动手练习

  1. 基础练习:修改 MessageService,让它返回带有当前时间的消息,验证 Bean 是否正常工作。
  2. 进阶练习:添加一个 GreetingService Bean,注入到 MessageController 中,实现根据用户名称返回个性化问候语。
  3. 挑战练习:尝试使用 XML 配置方式(ClassPathXmlApplicationContext)实现同样的功能,对比两种配置方式的差异。

5. 小结

本章我们从 Spring 的诞生背景出发,理解了 Spring 的核心理念:通过 IoC 和 AOP 简化 Java 开发。掌握了 Spring Framework 6.x 的四个核心升级特性(Java 17+、Jakarta EE、AOT、虚拟线程),并完成了第一个全注解 Spring 程序的开发。

关键知识点回顾:

  • Spring 生态 = Framework + Boot + Cloud + Data + Security + AI
  • Spring 6.x 最低要求 Java 17,使用 jakarta.* 命名空间
  • @Configuration + @ComponentScan + @Component/@Service 构成全注解开发的基础
  • AnnotationConfigApplicationContext 是注解驱动开发的容器入口

6. 面试实战题

题1:Spring 框架的核心特性是什么?

答案:Spring 的核心特性包括:

  1. IoC(控制反转):将对象的创建和管理权交给 Spring 容器,而不是由开发者手动 new 对象。通过 DI(依赖注入)实现对象之间的解耦。
  2. AOP(面向切面编程):将横切关注点(日志、事务、安全)从业务逻辑中分离,实现无侵入式增强。
  3. 模块化设计:Spring 由约 20 个模块组成,可以按需引入。
  4. 声明式事务:通过 @Transactional 注解实现声明式事务管理,无需手动编写事务代码。
  5. 生态丰富:Spring Boot、Spring Cloud、Spring Security 等子项目覆盖了企业开发的方方面面。

题2:Spring 6.x 相比 Spring 5.x 有哪些重大变化?

答案

  1. Java 17+ 基线:不再支持 Java 8/11,全面拥抱 Records、Sealed Classes 等特性。
  2. Jakarta EE 9+javax.* 全部迁移到 jakarta.*,这是最大的 Breaking Change。
  3. AOT 编译:支持 GraalVM 原生镜像,启动速度从秒级降到毫秒级。
  4. 虚拟线程:支持 Java 21 虚拟线程,高并发性能大幅提升。
  5. 移除旧 API:清理了大量过时的 API 和废弃代码,框架更精简。
  6. @Fallback Bean(6.2 新增):支持主 Bean 不可用时自动切换到备选 Bean。

题3:Spring 的模块化设计是怎样的?各模块的职责是什么?

答案:Spring 分为六大模块组:

  • 核心容器(Core Container):spring-core(工具类)、spring-beans(Bean 工厂)、spring-context(应用上下文)、spring-expression(SpEL)
  • AOP:spring-aop(代理 AOP)、spring-aspects(AspectJ 集成)
  • 数据访问:spring-jdbc(JdbcTemplate)、spring-orm(ORM 集成)、spring-tx(事务管理)
  • Web:spring-web(基础 Web)、spring-webmvc(MVC)、spring-webflux(响应式)
  • 测试:spring-test(集成测试支持)

题4:@Configuration 和 @Component 有什么区别?

答案

  • @Component 是通用的组件注解,标记一个类为 Spring Bean。
  • @Configuration@Component 的特殊形式,标记一个类为配置类,用于定义 @Bean 方法。
  • 关键区别:@Configuration 类中的 @Bean 方法会被 CGLIB 代理,确保单例 Bean 的方法调用始终返回同一个实例(Full 模式);而普通 @Component 类中的 @Bean 方法不会被代理(Lite 模式)。
  • 最佳实践:配置类使用 @Configuration,业务组件使用 @Service@Repository@Controller 等。

题5:ApplicationContext 和 BeanFactory 的区别是什么?

答案

特性 BeanFactory ApplicationContext
定位 底层 IoC 容器接口 高级容器接口(继承 BeanFactory)
Bean 加载 延迟加载(使用时才创建) 预加载(启动时创建所有单例 Bean)
国际化 不支持 支持 MessageSource
事件发布 不支持 支持 ApplicationEvent
资源加载 不支持 支持 ResourceLoader
使用场景 资源受限环境(如 Applet) 几乎所有企业应用

扩展:ApplicationContext 在启动时预加载所有单例 Bean,可以尽早发现配置错误。BeanFactory 延迟加载适合内存敏感的场景,但现代开发中几乎都用 ApplicationContext。


来源引用

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐