乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 Spring概述与IoC容器

    • Spring概述与IoC容器
    • Spring Framework 概述
    • IoC 与 DI 核心概念
    • @Configuration 详解
    • @Component 详解
    • @ComponentScan 详解
    • @Import 详解
    • @Profile 详解
    • @PropertySource 详解
    • @Service 详解
    • @Repository 详解
  • 第2章 Bean的定义与依赖注入

    • Bean的定义与依赖注入
    • @Bean 详解
    • @Autowired 详解
    • @Qualifier 详解
    • @Primary 详解
    • @Resource 详解
    • @Inject 详解
    • @Named 详解
    • @Value 详解
    • @Scope 详解
    • @Lazy 详解
  • 第3章 Bean生命周期与作用域

    • Bean生命周期与作用域
    • Bean生命周期概述
    • @PostConstruct
    • @PreDestroy
    • InitializingBean
    • DisposableBean
    • BeanPostProcessor
    • BeanFactoryPostProcessor
  • 第4章 AOP面向切面编程

    • AOP面向切面编程
    • AOP核心概念
    • @EnableAspectJAutoProxy
    • @Aspect
    • @Pointcut
    • @Before
    • @After
    • @AfterReturning
    • @AfterThrowing
    • @Around
  • 第5章 数据访问与事务管理

    • 数据访问与事务管理
    • 数据访问概述
    • @EnableTransactionManagement
    • @Transactional
    • @Transactional 的传播行为
    • @Transactional 的隔离级别
    • @Transactional 的回滚规则
    • @Transactional 的超时与只读属性
    • @TransactionalEventListener
  • 第6章 Spring Boot自动配置基础

    • Spring Boot自动配置基础
    • @SpringBootApplication 注解
    • @EnableAutoConfiguration 注解
    • @ConfigurationProperties 注解
    • @ConditionalOnClass 注解
    • @ConditionalOnMissingBean 注解
    • @ConditionalOnProperty 注解
  • 第7章 从容器到Web: Spring MVC导引

    • Spring MVC 导引
  • 第8章 扩展阅读

    • 扩展阅读
    • Spring 事件机制 — ApplicationEvent / ApplicationListener
    • @EventListener
    • SpEL — Spring 表达式语言
    • 校验 Validation — JSR-303 / JSR-380 Bean Validation
    • 类型转换与数据绑定 — Converter / DataBinder
  • 附录

    • Spring Framework 专业术语
    • Spring 核心知识点
    • Spring 面试高频考点
    • Spring 核心注解速查表

Spring Framework 概述

本章定位:在正式学习 IoC 容器之前,先建立对 Spring Framework 的全局认知。理解 Spring 是什么、为什么存在、由哪些模块组成,以及它与 Jakarta EE 生态的关系。


Spring 是什么

Spring Framework 是一个企业级 Java 应用开发框架,诞生于 2003 年,旨在简化早期 J2EE(Java 2 Platform, Enterprise Edition)的复杂性。它提供了从配置模型到依赖注入机制、从数据访问到 Web 开发的全栈支持,同时兼容 Groovy 和 Kotlin 作为 JVM 上的替代语言。

在 Spring 出现之前,开发一个企业级 Java 应用意味着要面对 EJB(Enterprise JavaBeans)的繁重配置、JNDI 查找的繁琐流程,以及应用服务器强绑定的部署模式。Spring 的创始人 Rod Johnson 在《Expert One-on-One J2EE Design and Development》一书中提出了"轻量级容器"的理念,随后 Spring Framework 应运而生。

设计哲学

Spring 的设计哲学可以概括为五点:

设计原则含义
提供选择(Provide choice)在每个层面都允许推迟设计决策,例如通过配置切换持久层框架而无需修改代码
容纳多样视角(Accommodate diverse perspectives)拥抱灵活性,不强制规定做事方式,支持不同应用场景
强向后兼容(Strong backward compatibility)版本演进谨慎,尽量减少破坏性变更
关注 API 设计(Care about API design)投入大量精力使 API 直观且经得起多版本考验
高代码质量标准(High standards for code quality)强调有意义的 Javadoc,保持包之间无循环依赖的干净结构

这五条原则贯穿 Spring 的每一个版本迭代。例如,Spring Framework 5.x 引入响应式编程模型(WebFlux)时,并没有废弃原有的 Spring MVC,而是让两者并存,这正是"容纳多样视角"的体现。


Spring Framework 模块总览

Spring Framework 采用模块化设计,应用可按需选择模块。核心为 Core Container(核心容器),包括配置模型和依赖注入机制;之外还提供消息、事务数据与持久化、Web 等基础支持。

模块路径说明:Spring Framework 的 JAR 包支持部署到 Java 模块路径(Java Module System),每个 JAR 都带有 Automatic-Module-Name 清单条目,定义稳定的语言级模块名(如 spring.core、spring.context),与 JAR 文件名(spring-core、spring-context)对应。

核心容器(Core Container)

核心容器是 Spring 的根基,包含四个模块:

  • spring-core:提供工具类、ASM 字节码操作支持,以及 Spring 的基础抽象
  • spring-beans:提供 BeanFactory 和依赖注入机制
  • spring-context:在 spring-beans 基础上扩展出 ApplicationContext,支持国际化、事件传播、资源加载
  • spring-expression:提供 SpEL(Spring Expression Language)表达式语言支持

数据访问与集成(Data Access/Integration)

  • spring-jdbc:简化 JDBC 操作,提供 JdbcTemplate
  • spring-tx:提供声明式事务管理抽象
  • spring-orm:集成 Hibernate、JPA 等 ORM 框架
  • spring-jms:集成消息队列(JMS)

Web 层

  • spring-web:提供基础的 Web 工具类(如文件上传、HTTP 客户端抽象)
  • spring-webmvc:传统的 Servlet MVC 框架
  • spring-webflux:Spring 5 引入的响应式 Web 框架
  • spring-websocket:WebSocket 支持

Spring 与 Jakarta EE 的关系

Spring 并非 Jakarta EE 的竞争对手,而是互补关系。Spring 编程模型不拥抱完整的 Jakarta EE 平台规范,而是选择性集成其中的个体规范:

规范JSR在 Spring 中的作用
Servlet APIJSR 340Spring MVC 的底层基础
WebSocket APIJSR 356Spring WebSocket 支持
Concurrency UtilitiesJSR 236异步任务调度
JSON Binding APIJSR 367JSON 序列化/反序列化
Bean ValidationJSR 303数据校验(如 @Valid)
JPAJSR 338ORM 集成(Hibernate 等)
JMSJSR 914消息队列集成
JSR-330JSR 330依赖注入标准注解(@Inject 等)

自 Spring Framework 6.0 起,Spring 已升级至 Jakarta EE 9 级别(如 Servlet 5.0+、JPA 3.0+),使用 jakarta 命名空间替代传统的 javax 包。但在 Spring 5.x / Spring Boot 2.x 中,仍然使用 javax 命名空间。


完整示例:飞翔科技公司的技术选型

场景简述

广州飞翔科技有限公司成立于 2018 年,技术部负责人大翔决定为公司新开发的"学生管理系统"选择技术栈。架构师白歌建议采用 Spring Framework 5.x 作为基础框架,后端开发小崔负责具体搭建。

操作前:纯 Servlet + JDBC 的原始实现

在没有 Spring 之前,小崔需要手动管理数据库连接、事务和对象依赖:

// 操作前:StudentDao.java —— 纯 JDBC,无框架支持
public class StudentDao {
    private DataSource dataSource;

    public StudentDao() {
        // 手动创建连接池,硬编码配置
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/student_db");
        config.setUsername("root");
        config.setPassword("secret");
        this.dataSource = new HikariDataSource(config);
    }

    public Student findById(int studentId) throws SQLException {
        Connection conn = dataSource.getConnection();
        PreparedStatement ps = conn.prepareStatement(
            "SELECT id, name, age, class_name FROM students WHERE id = ?"
        );
        ps.setInt(1, studentId);
        ResultSet rs = ps.executeQuery();

        Student student = null;
        if (rs.next()) {
            student = new Student();
            student.setId(rs.getInt("id"));
            student.setName(rs.getString("name"));
            student.setAge(rs.getShort("age"));
            student.setClassName(rs.getString("class_name"));
        }

        rs.close();
        ps.close();
        conn.close();  // 如果前面抛异常,这里可能执行不到,导致连接泄漏
        return student;
    }
}
// 操作前:StudentService.java —— 手动创建依赖,紧耦合
public class StudentService {
    private StudentDao studentDao = new StudentDao();  // 硬编码依赖
    private EmailSender emailSender = new EmailSender(); // 硬编码依赖

    public void enrollStudent(Student student) {
        try {
            studentDao.save(student);
            emailSender.send("admin@learnto.cn", "新学生入学:" + student.getName());
        } catch (SQLException e) {
            // 事务?不存在的,只能手动 rollback
            throw new RuntimeException("入学失败", e);
        }
    }
}

痛点分析:

  1. 连接泄漏:conn.close() 在异常时可能不执行
  2. 配置硬编码:数据库连接信息写死在代码里
  3. 依赖紧耦合:StudentService 自己 new 依赖对象,无法替换实现
  4. 无事务管理:入学操作涉及"保存学生"和"发送邮件",失败时无法统一回滚

操作后:引入 Spring Framework 的模块化架构

白歌为团队设计了基于 Spring 5.x 的模块依赖图:

// 操作后:AppConfig.java —— Spring 配置类
@Configuration
@ComponentScan("com.feixiang.student")
@PropertySource("classpath:application.properties")
public class AppConfig {

    @Bean
    public DataSource dataSource(
            @Value("${db.url}") String url,
            @Value("${db.username}") String username,
            @Value("${db.password}") String password) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(url);
        config.setUsername(username);
        config.setPassword(password);
        return new HikariDataSource(config);
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}
// 操作后:StudentDao.java —— 使用 Spring JDBC
@Repository
public class StudentDao {
    private final JdbcTemplate jdbcTemplate;

    public StudentDao(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public Student findById(int studentId) {
        return jdbcTemplate.queryForObject(
            "SELECT id, name, age, class_name FROM students WHERE id = ?",
            new BeanPropertyRowMapper<>(Student.class),
            studentId
        );
    }

    public void save(Student student) {
        jdbcTemplate.update(
            "INSERT INTO students(name, age, class_name) VALUES(?, ?, ?)",
            student.getName(), student.getAge(), student.getClassName()
        );
    }
}
// 操作后:StudentService.java —— 依赖注入 + 声明式事务
@Service
public class StudentService {
    private final StudentDao studentDao;
    private final EmailSender emailSender;

    public StudentService(StudentDao studentDao, EmailSender emailSender) {
        this.studentDao = studentDao;
        this.emailSender = emailSender;
    }

    @Transactional
    public void enrollStudent(Student student) {
        studentDao.save(student);
        emailSender.send("admin@learnto.cn", "新学生入学:" + student.getName());
    }
}

运行结果及分析

容器启动日志:
[main] INFO  o.s.c.a.AnnotationConfigApplicationContext - 
    Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6d06d69c
[main] INFO  o.s.b.f.s.DefaultListableBeanFactory - 
    Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5f2108b5:
    defining beans [appConfig,studentDao,studentService,emailSender,dataSource,jdbcTemplate];
    root of factory hierarchy
[main] DEBUG o.s.jdbc.core.JdbcTemplate - 
    Executing prepared SQL update [INSERT INTO students...]
[main] DEBUG o.s.j.d.DataSourceTransactionManager - 
    Initiating transaction commit

改进点总结:

维度操作前(纯 JDBC)操作后(Spring)
连接管理手动获取/释放,易泄漏JdbcTemplate 自动管理
配置管理硬编码在代码中@Value + application.properties 外部化
依赖管理new 硬编码,紧耦合构造器注入,松耦合,可测试
事务管理无,异常时数据不一致@Transactional 声明式事务,自动回滚
异常处理原始 SQLExceptionSpring 自动转换为 DataAccessException 体系

易错场景与面试考点

反例一:混淆 Spring Framework 与 Spring Boot

// ❌ 错误认知:以为 Spring Boot 是 Spring 的替代品
@SpringBootApplication  // 这是 Spring Boot 的注解,不是 Spring Framework 原生
public class StudentApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudentApplication.class, args);
    }
}

纠正:Spring Boot 是基于 Spring Framework 的快速启动层,它本身不是替代关系。Spring Boot 的自动配置底层仍然是 Spring Framework 的 ApplicationContext 和 @Configuration 机制。在 985 高校的计算机专业课程中,必须先掌握 Spring Framework 的核心容器原理,再学习 Spring Boot 的自动配置,否则会出现"只会用注解,不懂容器原理"的空中楼阁现象。

反例二:模块依赖缺失导致 ClassNotFoundException

小崔在 Maven 中只引入了 spring-context,却试图使用 @Transactional:

<!-- ❌ 错误:缺少 spring-tx 模块 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.21</version>
</dependency>

运行时报错:

java.lang.ClassNotFoundException: org.springframework.transaction.annotation.Transactional

纠正:@Transactional 属于 spring-tx 模块,必须显式引入:

<!-- ✅ 正确:按需引入事务模块 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.21</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.21</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.21</version>
</dependency>

面试高频题

Q1:Spring Framework 与 Jakarta EE 是什么关系?

Spring 不是 Jakarta EE 的竞争对手,而是互补关系。Spring 选择性集成 Jakarta EE 中的个体规范(如 Servlet、JPA、JMS),提供更轻量、更灵活的编程模型。Spring 5.x 使用 javax 命名空间,Spring 6.x 升级至 Jakarta EE 9,使用 jakarta 命名空间。

Q2:Spring 的核心容器包含哪些模块?

核心容器(Core Container)包含 spring-core、spring-beans、spring-context 和 spring-expression 四个模块。其中 spring-beans 提供 BeanFactory 和依赖注入,spring-context 在此基础上扩展出 ApplicationContext。

Q3:为什么 Spring 被称为"轻量级"框架?

"轻量级"是相对早期 EJB 而言。Spring 不强制要求应用服务器,可以在普通 Servlet 容器甚至独立 Java 应用中运行;同时采用 POJO(Plain Old Java Object)编程模型,不侵入业务代码的类继承结构。

上一页
Spring概述与IoC容器
下一页
IoC 与 DI 核心概念