【深入理解@EnableCaching】

server/2024/12/25 11:48:24/

深入理解@EnableCaching

@EnableCaching 是 Spring Framework 中用于启用和配置缓存机制的一个注解。它通常被应用在配置类上,用来告诉 Spring 容器需要激活缓存相关的功能。Spring 的缓存抽象提供了一种简单的机制来管理缓存,可以减少重复的计算或数据库查询,从而提高应用程序的性能。

使用 @EnableCaching

当你在配置类上使用 @EnableCaching 注解时,Spring 会自动检测并注册所有与缓存相关的 Bean(例如 CacheManagerCacheResolver),并且会对带有缓存相关注解的方法进行拦截,如 @Cacheable@CachePut@CacheEvict

缓存注解

  • @Cacheable:当方法被调用时,Spring 会检查缓存中是否已经存在结果。如果存在,则直接返回缓存的结果,而不执行实际的方法;如果不存在,则执行方法,并将结果存入缓存。
  • @CachePut:无论缓存中是否存在数据,都会执行方法,并将方法的结果存入缓存。
  • @CacheEvict:用于从缓存中移除数据。可以指定在方法执行前或后移除。

自定义缓存解析器

除了基本的注解外,你还可以自定义 CacheResolver 来决定使用哪个缓存或如何解析缓存键。这可以通过实现 CacheResolver 接口或使用 SimpleCacheResolver 来完成。

配置 CacheManager

为了使缓存工作,你需要配置一个或多个 CacheManager,它们负责创建和管理缓存。Spring 支持多种类型的 CacheManager,比如基于 EhCache、Caffeine、ConcurrentMap 等的实现。你可以通过 Java 配置或者 XML 来定义 CacheManager

模式选项

@EnableCaching 注解还有一个可选的 mode 属性,它可以接受以下值:

  • proxy (默认):使用代理的方式来拦截被缓存注解标注的方法。这是最常用的模式,适用于大多数场景。

  • aspectj:使用 AspectJ 编译期织入的方式来进行拦截。这种方式可以在不改变字节码的情况下对方法进行拦截,但是需要额外的编译步骤。

使用示例

1. 添加依赖

首先,确保你的 pom.xmlbuild.gradle 文件中包含了 Spring Cache 和你选择的缓存提供者的依赖。这里我们以 Spring Boot 项目为例,使用 Maven 构建工具,并且不引入特定的第三方缓存库,而是使用 Spring 内置的 ConcurrentMapCacheManager

pom.xml 中添加:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

创建一个配置类来启用缓存并定义 CacheManager

java">import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {// 定义两个缓存:books 和 authorsreturn new ConcurrentMapCacheManager("books", "authors");}
}

3. 使用缓存注解

接下来,我们创建一个服务类,其中包含一些被缓存注解标注的方法。

java">import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;@Service
public class BookService {// 模拟的数据存储private final Map<Long, String> bookStore = new ConcurrentHashMap<>();// 使用 @Cacheable 注解,尝试从 "books" 缓存中获取数据@Cacheable(value = "books", key = "#id")public String findBookById(Long id) {System.out.println("查询书籍: " + id);return bookStore.getOrDefault(id, "未知书籍");}// 使用 @CachePut 注解,更新或插入缓存中的数据@CachePut(value = "books", key = "#book.id")public String saveBook(Book book) {System.out.println("保存书籍: " + book);bookStore.put(book.getId(), book.getName());return book.getName();}// 使用 @CacheEvict 注解,移除缓存中的数据@CacheEvict(value = "books", key = "#id")public void deleteBookById(Long id) {System.out.println("删除书籍: " + id);bookStore.remove(id);}
}// 假设有一个简单的 Book 类
class Book {private Long id;private String name;// Getters and Setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Book{" +"id=" + id +", name='" + name + '\'' +'}';}
}

4. 测试缓存功能

为了测试上面定义的缓存逻辑,你可以编写一个控制器或者直接在主应用程序中调用这些服务方法。这里我们将通过控制台输出来简单地测试一下。

java">import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
public class CacheTestRunner implements CommandLineRunner {private final BookService bookService;@Autowiredpublic CacheTestRunner(BookService bookService) {this.bookService = bookService;}@Overridepublic void run(String... args) throws Exception {// 第一次查询会打印日志并返回默认值System.out.println("第一次查询: " + bookService.findBookById(1L));// 保存书籍到缓存Book book = new Book();book.setId(1L);book.setName("Spring in Action");bookService.saveBook(book);// 第二次查询应该不会打印日志,因为数据已经在缓存中System.out.println("第二次查询: " + bookService.findBookById(1L));// 删除书籍并清除缓存bookService.deleteBookById(1L);// 再次查询应该会打印日志并返回默认值System.out.println("第三次查询: " + bookService.findBookById(1L));}
}

​ 当你运行这个 Spring Boot 应用程序时,你会看到控制台上输出的日志信息,这表明了缓存是如何工作的。第一次调用 findBookById 方法时,由于缓存中没有数据,它会执行实际的方法逻辑;而第二次调用时,它应该直接从缓存中获取数据,不再打印“查询书籍”的日志;最后,当删除书籍后,再次查询该书籍时,它又会执行实际的方法逻辑,因为缓存已经被清除了。

​ 这个例子展示了如何使用 @EnableCaching 启用缓存功能,并使用 @Cacheable@CachePut@CacheEvict 注解来管理缓存。当然,实际应用中可能会更加复杂,但这是一个很好的起点。

注意事项

  • @EnableCaching 只有在 Spring 上下文启动时才会生效,因此不能动态地开启或关闭缓存。
  • 缓存注解只对公共方法有效。如果你尝试在非公共方法上使用缓存注解,它们将不会起作用。
  • 在使用缓存时要考虑到缓存一致性的问题,确保缓存的数据是最新的,以避免出现脏读的情况。

总之,@EnableCaching 是 Spring 提供的一种强大而灵活的工具,可以帮助开发者轻松地添加缓存逻辑到他们的应用程序中。正确配置和使用它能够显著提升应用的响应速度和效率。


http://www.ppmy.cn/server/153030.html

相关文章

人工智能学习框架入门教程(一)

人工智能&#xff08;AI&#xff09;学习框架是指为开发、训练和部署人工智能模型提供的结构化工具和环境。它们帮助开发者实现AI项目的高效性、可扩展性、可维护性&#xff0c;并提供了优化算法、模型训练、评估、调优等功能。根据任务的不同&#xff0c;人工智能框架可以分为…

云边端架构的优势是什么?面临哪些挑战?

一、云边端架构的优势 降低网络延迟&#xff1a;在传统集中式架构中&#xff0c;数据需传输到云计算中心处理&#xff0c;导致网络延迟较高。而云边端架构将计算和存储推向边缘设备&#xff0c;可在离用户更近的地方处理数据&#xff0c;大大降低了网络延迟&#xff0c;提升了用…

ETCD备份还原

环境准备&#xff1a; master 192.168.8.128 node1 192.168.8.129 k8s版本&#xff1a; 一&#xff1a;安装etcdctl工具 1.1下载安装包&#xff1a; wget https://github.com/etcd-io/etcd/releases/download/v3.4.13/etcd-v3.4.13-linux-amd64.tar.gz 1.2解压&…

用于汽车碰撞仿真的 Ansys LS-DYNA

使用 Ansys LS-DYNA 进行汽车碰撞仿真汽车碰撞仿真 简介 汽车碰撞仿真是汽车设计和安全工程的一个关键方面。这些仿真使工程师能够预测车辆在碰撞过程中的行为&#xff0c;从而有助于改进安全功能、增强车辆结构并符合监管标准。Ansys LS-DYNA 是一款广泛用于此类仿真的强大工具…

国自然联合项目|影像组学智能分析理论与关键技术|基金申请·24-12-25

小罗碎碎念 该项目为国自然联合基金项目&#xff0c;执行年限为2019年1月至2022年12月&#xff0c;直接费用为204万元。 项目研究内容包括影像组学分析、智能计算、医疗风险评估等&#xff0c;旨在通过模拟医生诊断过程&#xff0c;推动人工智能在医疗领域的创新。 项目取得了…

命令行音乐库管理工具Beets

什么是 Beets &#xff1f; Beets 是一个音乐库管理系统和音乐文件元数据标签编辑器。它使用 MusicBrainz 数据库来自动填充音乐文件的元数据信息&#xff0c;并且可以通过插件系统来增加各种额外功能&#xff0c;比如自动下载专辑封面&#xff0c;歌词等。其目的是使您的音乐收…

深度学习解pde,心电图一般的损失。。

在机器学习和深度学习中&#xff0c;损失突然增加可能有多种原因。以下是一些常见的原因以及如何应对它们&#xff1a; 权重初始化不当&#xff1a;如果网络层的权重没有被正确地初始化&#xff0c;可能会导致训练不稳定&#xff0c;甚至发散。常见的解决方案包括使用Xavier/Gl…

【1224】C选填(字符串\0占大小,类大小函数调用,const定义常量,逗号表达式取尾,abs返回值

1.设有数组定义: char array[]"China"; 则数组array所占的存储空间为__________ 6 注意要加上\0的位置 数组中考虑‘\0’&#xff0c;sizeof()判断大小也要考虑‘\0’ 2.初始化数组char[] strArray"kuai-shou"&#xff0c;strArray的长度为&#xff08;&am…