当前位置: 首页 > news >正文

在Spring Boot中使用进程内缓存和Cache注解

在Spring Boot中使用内缓存的时候需要预先知道什么是内缓存,使用内缓存的好处。

什么是内缓存

内缓存(也称为进程内缓存或本地缓存)是指将数据存储在应用程序的内存中,以便在需要时快速访问和检索数据,而无需每次都从外部数据源(如数据库或网络)获取数据。

内缓存通常用于提高应用程序的性能和响应速度,因为内存访问比磁盘或网络访问更快。通过将经常使用的数据存储在内存中,应用程序可以避免频繁地访问慢速的外部数据源,从而提高数据访问的效率。

内缓存可以用于各种场景,例如:

  • 数据库查询结果缓存:将数据库查询的结果存储在内存中,以便在相同的查询被再次执行时,可以直接从缓存中获取结果,而无需再次查询数据库。
  • API响应缓存:将API的响应结果存储在内存中,以便在相同的API请求被再次发起时,可以直接从缓存中获取响应结果,而无需再次调用外部API。
  • 计算结果缓存:将复杂的计算结果存储在内存中,以便在相同的计算被再次触发时,可以直接从缓存中获取结果,而无需重新执行计算逻辑。

内缓存可以使用各种缓存框架或库来实现,如Caffeine、EhCache、Redis等。这些缓存框架提供了方便的API和配置选项,使开发人员能够轻松地在应用程序中使用内缓存。

需要注意的是,内缓存是存储在应用程序的内存中的,因此它的容量是有限的。过多地使用内缓存可能会导致内存占用过高,从而影响应用程序的性能。因此,在使用内缓存时,需要根据实际需求和可用内存来进行合理的配置和管理。

案例:

引入相关依赖:

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>

在配置文件中引入数据库相关属性:

spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

创建实体类对象,其中数据库对象和实体类对象一一对应,这里就不给出数据库SQL语句了:

@Entity
//@Data
//@NoArgsConstructor
public class User {@Id@GeneratedValueprivate Long id;private String name;private Integer age;public User(String name, Integer age) {this.name = name;this.age = age;}public 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;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public User() {}
}

User实体的数据访问实现:

@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Long> {@CacheableUser findByName(String name);User findByNameAndAge(String name, Integer age);@Query("from User u where u.name=:name")User findUser(@Param("name") String name);}

创建一个测试类:

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Autowiredprivate UserRepository userRepository;@Autowiredprivate CacheManager cacheManager;@Testpublic void test() throws Exception {// 创建1条记录userRepository.save(new User("AAA", 10));User u1 = userRepository.findByName("AAA");System.out.println("第一次查询:" + u1.getAge());User u2 = userRepository.findByName("AAA");System.out.println("第二次查询:" + u2.getAge());}}

需要在启动类中加入@EnableCaching注解:

@EnableCaching
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}

在这里插入图片描述

如图,我们可以看到在调用第二次的findByName的时候,并没有执行select语句,这样也就减少了对数据库的读取操作。

在这里插入图片描述

在这里插入图片描述
通过图片可以看到,在第一次调用findByName函数之后,CacheManager将这个查询结果保存下来,在第二次访问的时候,就可以匹配上而不需要再次访问数据库了。

@Cacheable:该注解用于标记方法的返回值应该被缓存。当调用带有@Cacheable注解的方法时,Spring Boot会首先检查缓存中是否存在对应的结果。如果存在,则直接返回缓存的结果;如果不存在,则执行方法体中的逻辑,并将结果存储到缓存中。该注解可以指定缓存的名称、缓存的键等参数。

@CachePut:该注解用于标记方法的返回值应该被更新到缓存中。与@Cacheable不同,@CachePut注解会每次都执行方法体中的逻辑,并将结果存储到缓存中。它通常用于更新缓存中的数据,以确保缓存的数据与实际数据保持同步。

@CacheEvict:该注解用于标记方法的返回值应该从缓存中移除。当调用带有@CacheEvict注解的方法时,Spring Boot会从缓存中移除对应的结果。该注解可以指定要移除的缓存名称、缓存的键等参数。它通常用于在数据发生变化时,清除缓存中的旧数据。

@Caching:该注解用于将多个缓存相关的注解组合在一起使用。通过@Caching注解,您可以在一个方法上同时使用多个缓存相关的注解,以实现更复杂的缓存操作。

关于更多的Cache配置,我们可以参照Spring Boot官方文档。

相关文章:

  • 当我只有一个代理,我该如何从内网搭建一个docker环境
  • edge/chrome浏览器favicon.ico缓存问题
  • TEMU要求提交RSL Report 铅镉RSL邻苯项目化学物质检测报告
  • Sentinel
  • Clickhouse学习笔记
  • 【博客系统】 二
  • Vue 路由使用
  • 虚幻C++ day5
  • 【matlab学习】组合系统的模型计算
  • 人工智能基础_机器学习039_sigmoid函数_逻辑回归_逻辑斯蒂回归_分类神器_代码实现逻辑回归图---人工智能工作笔记0079
  • 微信小程序rich-text 文本首行缩进和图片居中和富文本rich-text 解析多个空格不成功 nbsp
  • 机器视觉兄弟们,职场要不要王自如,如果你打工了,你就是被“包养”,就不要谈什么独立人格!
  • Zookeeper学习笔记(1)—— 基础知识
  • 蓝桥杯每日一题2023.11.14
  • 世界上最便宜好用的服务器低至 $9.99 / 年
  • Brief introduction of how to 'Call, Apply and Bind'
  • ECMAScript入门(七)--Module语法
  • mockjs让前端开发独立于后端
  • mysql 数据库四种事务隔离级别
  • Node项目之评分系统(二)- 数据库设计
  • Python学习之路13-记分
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • vue的全局变量和全局拦截请求器
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 使用agvtool更改app version/build
  • 网页视频流m3u8/ts视频下载
  • 终端用户监控:真实用户监控还是模拟监控?
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • ​​​​​​​​​​​​​​Γ函数
  • ​queue --- 一个同步的队列类​
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (C++20) consteval立即函数
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (九)信息融合方式简介
  • (强烈推荐)移动端音视频从零到上手(下)
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .Net 8.0 新的变化
  • .NET Project Open Day(2011.11.13)
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • [20171106]配置客户端连接注意.txt
  • [CareerCup][Google Interview] 实现一个具有get_min的Queue
  • [ffmpeg] av_opt_set 解析
  • [hihocoder1395] 最大权闭合子图
  • [HOW TO]怎么在iPhone程序中实现可多选可搜索按字母排序的联系人选择器
  • [IDF]摩斯密码