欢迎光临
我们一直在努力

Spring 核心知识点全解析(续)

七、Spring 事务控制 – 核心重点

在上述转账测试中,如果在扣钱和加钱之间抛出异常(如int a = 6/0;),会出现扣钱成功、加钱失败的情况,违反数据库事务的一致性。Spring 提供了完善的事务控制方案,基于 AOP 实现无侵入式的事务管理,解决该问题。

7.1 事务的核心概念

7.1.1 数据库事务四大特性(ACID)
  • 原子性(Atomicity):事务是最小执行单位,要么全部执行,要么全部回滚;
  • 一致性(Consistency):事务执行前后,数据库数据状态保持合法;
  • 隔离性(Isolation):多个并发事务之间相互隔离,互不干扰;
  • 持久性(Durability):事务提交后,数据修改永久生效,不会丢失。
  • 7.1.2 事务并发的三大问题
    问题描述
    脏读 一个事务读取到另一个事务未提交的数据
    不可重复读 一个事务内多次读取同一数据,结果不一致(被其他事务修改并提交)
    幻读 一个事务内多次读取同一表,结果条数不一致(被其他事务插入 / 删除并提交)

    7.2 Spring 事务控制核心 API

    Spring 事务控制基于 AOP 实现,核心有 3 个接口,均在org.springframework.transaction包下:

    7.2.1 PlatformTransactionManager(事务管理器)

    核心作用:提供事务的开启、提交、回滚核心方法,是 Spring 事务控制的核心接口,针对不同的持久层框架有不同的实现类:

    实现类适用场景
    DataSourceTransactionManager 适用于 Spring JDBC/MyBatis/MyBatis-Spring
    HibernateTransactionManager 适用于 Hibernate 框架
    JpaTransactionManager 适用于 JPA 框架

    public interface PlatformTransactionManager {
    // 开启事务,返回事务状态
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    // 提交事务
    void commit(TransactionStatus status) throws TransactionException;
    // 回滚事务
    void rollback(TransactionStatus status) throws TransactionException;
    }

    7.2.2 TransactionDefinition(事务定义)

    核心作用:定义事务的属性,如隔离级别、传播行为、超时时间、读写性等,核心属性如下:

    (1)事务隔离级别

    解决事务并发的三大问题,Spring 提供 5 种隔离级别(默认使用数据库默认隔离级别,MySQL 为 REPEATABLE_READ,Oracle 为 READ_COMMITTED):

    隔离级别说明
    ISOLATION_DEFAULT 默认值,使用数据库自身的隔离级别
    ISOLATION_READ_UNCOMMITTED 最低级别,允许脏读、不可重复读、幻读
    ISOLATION_READ_COMMITTED 避免脏读,允许不可重复读、幻读
    ISOLATION_REPEATABLE_READ 避免脏读、不可重复读,允许幻读
    ISOLATION_SERIALIZABLE 最高级别,避免所有并发问题,事务串行执行
    (2)事务传播行为

    核心作用:定义一个事务方法被另一个事务方法调用时,事务的执行规则(如是否新建事务、是否加入原有事务),Spring 提供 7 种传播行为,PROPAGATION_REQUIRED为最常用:

    传播行为说明
    PROPAGATION_REQUIRED 若当前无事务则新建,若有则加入(默认)
    PROPAGATION_SUPPORTS 支持当前事务,无事务则以非事务执行
    PROPAGATION_MANDATORY 必须在事务中执行,无事务则抛异常
    PROPAGATION_REQUIRES_NEW 强制新建事务,若有当前事务则挂起
    PROPAGATION_NOT_SUPPORTED 以非事务执行,若有当前事务则挂起
    PROPAGATION_NEVER 以非事务执行,若有当前事务则抛异常
    PROPAGATION_NESTED 嵌套事务,若当前有事务则在嵌套事务中执行
    (3)其他属性
    • 超时时间:事务执行的最长时间,超时则自动回滚,默认-1(永不超时);
    • 读写性:readOnly=true为只读事务(适用于查询,提高效率),readOnly=false为读写事务(适用于增删改,默认)。
    7.2.3 TransactionStatus(事务状态)

    核心作用:表示当前事务的状态信息,如是否是新事务、是否需要回滚等。

    7.3 基于 XML 的 Spring 事务控制(AOP 实现)

    Spring 事务控制基于 AOP 实现,核心是配置事务增强、切入点、切面,让事务逻辑织入到业务方法中。

    7.3.1 完善 Spring 配置文件

    在applicationContext.xml中添加事务管理器、事务增强、AOP 切面配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!– 原有配置:加载配置文件、数据源、SqlSessionFactory、Mapper扫描、注解扫描 –>
    <context:property-placeholder location="classpath:db.properties" />
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClass}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="typeAliasesPackage" value="com.hg.pojo"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.hg.mapper"/>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    <context:component-scan base-package="com.hg"></context:component-scan>

    <!– 新增事务配置 –>
    <!– 1. 配置事务管理器(MyBatis使用DataSourceTransactionManager) –>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    </bean>
    <!– 2. 配置事务增强(tx:advice),指定事务属性 –>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <!– 匹配业务方法,配置事务属性 –>
    <!– 所有方法:读写事务,传播行为REQUIRED –>
    <tx:method name="*" read-only="false" propagation="REQUIRED"/>
    <!– 以select/get开头的方法:只读事务,提高查询效率 –>
    <tx:method name="select*" read-only="true" propagation="SUPPORTS"/>
    <tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
    </tx:attributes>
    </tx:advice>
    <!– 3. 配置AOP切面,将事务增强织入到切入点 –>
    <aop:config>
    <!– 切入点:匹配Service层所有方法 –>
    <aop:pointcut id="txPointcut" expression="execution(* com.hg.service.*.*(..))"/>
    <!– 切面:事务增强 + 切入点 –>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>
    </beans>

    7.3.2 测试事务回滚

    修改UserServiceImpl的转账方法,手动抛出异常,测试事务是否回滚:

    @Override
    public void updateUser(String source, String target, Float money) {
    userMapper.updateUserOfSub(source, money);
    // 手动抛出算术异常,模拟业务出错
    int a = 6 / 0;
    userMapper.updateUserOfAdd(target, money);
    }

    重新执行testUpdate测试方法,控制台抛出异常,数据库中张三丰的余额未减少,宋远桥的余额未增加,说明事务回滚成功,解决了数据一致性问题!

    7.4 基于注解的 Spring 事务控制

    注解配置比 XML 配置更简洁,开发中更常用,核心注解为@Transactional,可标注在类或方法上。

    7.4.1 开启注解事务支持

    在applicationContext.xml中删除 XML 的事务增强和 AOP 配置,仅保留事务管理器和注解事务开启:

    <!– 事务管理器(必须保留) –>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    </bean>
    <!– 开启Spring注解事务支持 –>
    <tx:annotation-driven transaction-manager="transactionManager"/>

    7.4.2 使用 @Transactional 注解

    @Transactional可标注在类上(所有方法生效)或方法上(仅当前方法生效,方法注解优先级高于类注解),通过注解属性配置事务属性。

    package com.hg.service.impl;
    import com.hg.mapper.UserMapper;
    import com.hg.pojo.User;
    import com.hg.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;

    @Service
    // 类上标注:所有方法默认使用该事务属性
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    // 方法上标注:可单独配置(优先级更高)
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void updateUser(String source, String target, Float money) {
    userMapper.updateUserOfSub(source, money);
    int a = 6 / 0; // 手动抛异常
    userMapper.updateUserOfAdd(target, money);
    }

    @Override
    // 查询方法:只读事务
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public void addUser(User user) {
    userMapper.addUser(user);
    }
    }

    @Transactional核心属性与TransactionDefinition一致,常用属性:

    • readOnly:是否只读,默认false;
    • propagation:传播行为,默认Propagation.REQUIRED;
    • isolation:隔离级别,默认Isolation.DEFAULT;
    • timeout:超时时间,默认-1;
    • rollbackFor:指定触发回滚的异常类型,默认运行时异常回滚,检查异常不回滚。

    重新执行测试方法,事务依然能成功回滚,注解配置生效!

    八、Spring 核心知识点总结

    8.1 核心思想

  • IOC(控制反转):将对象的创建权从开发者转移到 Spring 容器,通过DI(依赖注入) 解决对象依赖,彻底消除硬编码耦合;
  • AOP(面向切面编程):将通用功能(日志、事务、权限) 与业务逻辑解耦,通过通知 + 切入点实现无侵入式功能增强,核心是动态代理(JDK 动态代理 + CGlib 动态代理);
  • 事务控制:基于 AOP 实现,通过声明式配置(XML / 注解)替代硬编码事务,保证数据库操作的 ACID 特性。
  • 8.2 配置方式对比

    配置方式优点缺点适用场景
    XML 配置 配置与代码分离,便于统一管理 配置文件繁琐,开发效率低 大型项目、需要统一管理配置
    注解配置 简洁高效,开发效率高 配置分散在代码中,不易维护 中小型项目、快速开发
    纯注解配置(Spring Boot) 无 XML,极致简洁 需熟悉注解规则 Spring Boot/Spring Cloud 项目

    8.3 开发最佳实践

  • 分层开发:严格遵循Controller→Service→Mapper分层,每层职责单一,通过 Spring 注解管理(@Controller/@Service/@Repository);
  • 依赖注入:优先使用@Autowired(按类型)+@Qualifier(按名称),避免硬编码 new 对象;
  • 事务控制:优先使用@Transactional注解,查询方法设为只读事务,增删改方法设为读写事务;
  • 整合 MyBatis:使用MapperScannerConfigurer自动扫描 Mapper,避免手动创建 SqlSession;
  • 测试:使用 Spring 整合 JUnit,避免手动创建 ApplicationContext 容器。
  • 8.4 后续学习方向

    掌握 Spring 核心(IOC+AOP + 事务)后,后续可深入学习:

  • Spring MVC:Spring 的 Web 层框架,实现 MVC 设计模式,与 Spring 无缝整合;
  • Spring Boot:简化 Spring 配置,实现自动配置、起步依赖、嵌入式容器,快速开发微服务;
  • Spring Cloud:基于 Spring Boot 的微服务框架,提供服务注册发现、配置中心、熔断降级等微服务能力;
  • Spring Security/Spring Shiro:基于 Spring 的权限控制框架,实现用户认证、授权、资源控制。
  • 九、常见问题与解决方案

  • 问题:@Autowired注入时报NoSuchBeanDefinitionException?解决方案:检查是否开启注解扫描(context:component-scan)、类是否添加了@Component/@Service等注解、Bean 的类型是否匹配。

  • 问题:Spring 整合 MyBatis 时,Mapper 注入时报错?解决方案:检查MapperScannerConfigurer的basePackage是否正确、Mapper 接口与 XML 的namespace是否一致、XML 文件是否被 Maven 扫描(需配置 build/resources)。

  • 问题:事务不回滚?解决方案:

    • 检查是否开启了注解事务支持(tx:annotation-driven);
    • 检查事务管理器是否注入了数据源;
    • 检查异常类型是否为运行时异常(默认仅运行时异常回滚,可通过rollbackFor指定检查异常);
    • 检查是否手动捕获了异常(若捕获未抛出,事务无法感知,需手动throw new RuntimeException())。
  • 问题:AOP 切面不生效?解决方案:检查是否开启 AOP 注解支持(aop:aspectj-autoproxy)、切面类是否添加@Aspect注解、切入点表达式是否正确匹配业务方法。


  • 本文完,从 Spring 概述到 IOC、AOP,再到整合 MyBatis 和事务控制,全面讲解了 Spring 的核心知识点,结合实战案例让理论落地。掌握这些内容,就能轻松应对日常开发中的 Spring 使用场景,也为后续学习 Spring Boot/Spring Cloud 打下坚实基础!

    赞(0)
    未经允许不得转载:171主机测评 » Spring 核心知识点全解析(续)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址