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.02004.03IoC 容器、AOP 支持、JDBC 模板
Spring 2.02006.10XML Schema 配置、注解支持、AspectJ 集成
Spring 2.52007.11@Autowired、@Component 注解驱动开发
Spring 3.02009.12JavaConfig、@Configuration、SpEL 表达式
Spring 4.02013.12Java 8 全面支持、@RestController、WebSocket
Spring 5.02017.09响应式编程(WebFlux)、Java 9+ 支持
Spring 6.02022.11Java 17+ 基线、Jakarta EE 9+、AOT 编译、虚拟线程预备
Spring 6.22024.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,这意味着:

  • 可以使用 Records、Sealed Classes、Pattern Matching、Text 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 的区别是什么?

答案:

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

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


来源引用:

Logo

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

更多推荐