思途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 事务 + 缓存 = 高可用、高性能应用的基石!

相关推荐
枫の准大一1 小时前
【C++游记】物种多样——谓之多态
开发语言·c++
JuneXcy3 小时前
循环高级(1)
c语言·开发语言·算法
MediaTea4 小时前
Python 第三方库:lxml(高性能 XML/HTML 解析与处理)
xml·开发语言·前端·python·html
编啊编程啊程4 小时前
响应式编程框架Reactor【2】
java
编啊编程啊程4 小时前
响应式编程框架Reactor【3】
java·开发语言
Ka1Yan4 小时前
什么是策略模式?策略模式能带来什么?——策略模式深度解析:从概念本质到Java实战的全维度指南
java·开发语言·数据结构·算法·面试·bash·策略模式
胡萝卜的兔5 小时前
go 使用rabbitMQ
开发语言·golang·rabbitmq
你我约定有三5 小时前
面试tips--java--equals() & hashCode()
java·开发语言·jvm
努力也学不会java6 小时前
【设计模式】简单工厂模式
java·开发语言·设计模式·简单工厂模式
就叫飞六吧6 小时前
基于Spring Boot的短信平台平滑切换设计方案
java·spring boot·后端