思途spring学习0807

一、Spring 事务管理(Transaction Management)

1. 事务基本配置步骤

Spring Boot 中使用声明式事务非常简单,只需三步:

✅ 步骤一:引入依赖(通常已包含)
复制代码
<!-- spring-boot-starter-data-jpa 或 mybatis-spring-boot-starter 已包含 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

⚠️ 实际上 spring-boot-starter-* 数据相关 starter 已默认集成事务支持,无需手动添加 AOP 依赖(但底层依赖 AOP 实现)。


✅ 步骤二:启用事务支持

在主启动类或配置类上添加 @EnableTransactionManagementSpring Boot 2.x+ 可省略,自动启用):

复制代码
@SpringBootApplication
@EnableTransactionManagement  // 可选,Spring Boot 默认开启
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

✅ 步骤三:使用 @Transactional 注解

标注在 Service 层的方法 上(不建议在 Controller 使用):

复制代码
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Transactional
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        userMapper.decreaseBalance(fromId, amount);
        // 模拟异常
        if (amount.compareTo(BigDecimal.TEN) > 0) {
            throw new RuntimeException("金额过大,转账失败");
        }
        userMapper.increaseBalance(toId, amount);
    }
}

✅ 效果:若方法中抛出异常(默认检查 RuntimeException 和 Error),事务将回滚;否则提交。


2. 事务隔离级别(Isolation Level)

隔离级别 说明 存在问题
READ_UNCOMMITTED 读未提交 脏读、不可重复读、幻读
READ_COMMITTED 读已提交 不可重复读、幻读
REPEATABLE_READ 可重复读 幻读(部分数据库可避免)
SERIALIZABLE 串行化 性能极低,排队执行

🔺 安全性递增,性能递减

🔹 默认值:ISOLATION_DEFAULT → 使用数据库默认隔离级别(MySQL 默认为 REPEATABLE_READ

复制代码
@Transactional(isolation = Isolation.READ_COMMITTED)
public void method() { ... }

3. 事务传播机制(Propagation Behavior)

Spring 定义了 7 种传播行为,控制多个事务方法调用时的事务边界。

传播行为 说明 使用场景
REQUIRED(默认) 必须有事务。若已有则加入,否则新建 增删改操作(CRUD-write)
SUPPORTS 支持事务。有则加入,无则非事务执行 查询方法(只读)
MANDATORY 必须运行在事务中,否则抛异常 强制要求调用者开启事务
REQUIRES_NEW 总是新建事务,挂起当前事务 日志记录、独立操作
NOT_SUPPORTED 不支持事务,挂起当前事务 批量导入等耗时操作
NEVER 不支持事务,若有事务则抛异常 确保非事务环境运行
NESTED 嵌套事务。外层回滚,内层也回滚;内层可独立回滚 复杂业务逻辑中的子事务控制

📌 示例:

复制代码
@Service
public class BusinessService {

    @Autowired
    private LogService logService;

    @Transactional(propagation = Propagation.REQUIRED)
    public void businessMethod() {
        // 主业务逻辑
        doBusiness();

        // 即使主事务失败,日志仍需记录
        logService.saveLog(); // 内部使用 REQUIRES_NEW
    }
}

@Service
public class LogService {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveLog() {
        // 新建事务,独立提交
    }
}

二、Spring 缓存机制(Caching Abstraction)

基于 AOP + 注解 实现,统一抽象缓存操作,支持多种缓存实现(如 Caffeine、Redis、EhCache 等)。


1. 核心注解

注解 作用
@EnableCaching 启用 Spring 缓存支持(加在启动类或配置类)
@Cacheable 方法执行前查缓存,命中则不执行方法
@CachePut 方法执行后更新缓存,总是执行方法
@CacheEvict 清除缓存(可清单个或全部)
@CacheConfig 类级别缓存配置(统一 cacheNames、keyGenerator 等)

2. Spring Boot 整合 Redis 缓存

✅ 步骤一:引入依赖
复制代码
<!-- Spring Data Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- Spring Cache 抽象 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

✅ 步骤二:配置文件(application.yml)
复制代码
spring:
  # Redis 配置
  data:
    redis:
      host: localhost
      port: 6379
      password: 123456
      database: 0
      timeout: 1s
      connect-timeout: 3s
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0

  # 缓存配置
  cache:
    type: redis
    redis:
      time-to-live: 4h           # 缓存过期时间(TTL)
      cache-null-values: false   # 是否缓存 null 值
    cache-names: userCache, deptCache  # 预定义缓存名称

✅ 步骤三:启用缓存
复制代码
@SpringBootApplication
@EnableCaching  // 启用缓存
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

✅ 步骤四:使用缓存注解
复制代码
@Service
@CacheConfig(cacheNames = "userCache")  // 统一指定缓存名
public class UserService {

    @Autowired
    private UserMapper userMapper;

    // 查询时先查缓存,key = userId
    @Cacheable(key = "#id")
    public User findById(Long id) {
        System.out.println("查询数据库...");
        return userMapper.findById(id);
    }

    // 更新后同步更新缓存
    @CachePut(key = "#user.id")
    public User update(User user) {
        userMapper.update(user);
        return user; // 返回值会自动放入缓存
    }

    // 删除用户,同时清除缓存
    @CacheEvict(key = "#id")
    public void deleteById(Long id) {
        userMapper.deleteById(id);
    }

    // 清空整个缓存
    @CacheEvict(allEntries = true)
    public void clearCache() {
        // ...
    }
}

3. Redis 五大数据类型简介

类型 特点 应用场景
String 字符串 缓存、计数器、分布式锁
List 有序、可重复 消息队列、最新消息列表
Set 无序、不重复 好友标签、共同关注
ZSet (Sorted Set) 有序集合,带 score 排序 排行榜、延迟队列
Hash 键值对集合 存储对象(如用户信息)

🔍 示例:用 Hash 存储用户信息

复制代码
opsHash.put("user:1001", "name", "张三");
opsHash.put("user:1001", "age", "25");

4. 缓存过期策略(TTL - Time To Live)

  • Redis 支持设置键的过期时间,单位秒或毫秒。

  • Spring Cache 中通过 time-to-live 配置全局 TTL。

  • 可在注解中单独设置:

    @Cacheable(key = "#id", ttl = 3600) // 单独设置过期时间(需自定义 CacheManager)


三、Caffeine vs Redis

对比项 Caffeine(本地缓存) Redis(分布式缓存)
存储位置 JVM 内存 独立服务
速度 极快(纳秒级) 快(毫秒级)
容量 受限于 JVM 大(可集群扩展)
一致性 单机一致 分布式一致
适用场景 高频读、低变更数据 共享数据、跨服务缓存

✅ 推荐组合使用:Caffeine + Redis(多级缓存)


四、最佳实践与注意事项

✅ 事务使用建议

  • 标注在 public 方法 上(AOP 代理限制)。
  • 避免在 private、final、static 方法上使用。
  • 异常要抛出,才能触发回滚。
  • 自调用(this.method())不会触发事务(代理失效)。

✅ 缓存使用建议

  • 合理设置 TTL,避免数据陈旧。
  • 缓存穿透:加空值缓存或布隆过滤器。
  • 缓存雪崩:设置随机过期时间。
  • 缓存击穿:热点数据加互斥锁。
  • 使用 @CacheConfig 统一管理缓存配置。

五、总结对比表

功能 事务(Transaction) 缓存(Caching)
实现机制 AOP + PlatformTransactionManager AOP + CacheManager
核心注解 @Transactional @Cacheable, @CachePut, @CacheEvict
配置注解 @EnableTransactionManagement @EnableCaching
性能影响 回滚代价高 显著提升读性能
典型场景 数据一致性保障 减少数据库压力

📌 学习建议

  • 动手实践事务传播行为(如 REQUIRED vs REQUIRES_NEW)。
  • 使用 Redis Desktop Manager 查看缓存数据。
  • 结合日志观察缓存命中情况。
  • 理解 AOP 是事务和缓存的底层支撑机制。

Spring 事务 + 缓存 = 高可用、高性能应用的基石!

相关推荐
雨绸缪2 分钟前
为什么 Java 在 2025 年仍然值得学习:开发人员的 25 年历程
java·后端·掘金·金石计划
蒋星熠20 分钟前
QT项目 -仿QQ音乐的音乐播放器(第五节)
开发语言·qt
叫我:松哥29 分钟前
基于Python的实习僧招聘数据采集与可视化分析,使用matplotlib进行可视化
开发语言·数据库·python·课程设计·matplotlib·文本挖掘
花花无缺36 分钟前
泛型类和泛型方法
java·后端
lqg_zone40 分钟前
基于 Socket.IO 实现 WebRTC 音视频通话与实时聊天系统(Spring Boot 后端实现)
spring boot·音视频·webrtc
澡点睡觉44 分钟前
golang的面向对象编程,struct的使用
开发语言·爬虫·golang
AI视觉网奇1 小时前
nohup 学习笔记
笔记·学习
泉城老铁1 小时前
Spring Boot 中实现 COM 口数据监听并解析十六进制数据,结合多线程处理
java·后端·物联网
一个尚在学习的计算机小白1 小时前
大模型学习笔记
笔记·学习
熊猫片沃子1 小时前
浅谈SpringBoot框架的优势
java·spring boot·后端