转载请注明出处:https://www.cnblogs.com/wenjunwei/p/10779450.html

spring基于注解的缓存

对于缓存声明,spring的缓存提供了一组java注解:

  • @Cacheable:触发缓存写入。
  • @CacheEvict:触发缓存清除。
  • @CachePut:更新缓存(不会影响到方法的运行)。
  • @Caching:重新组合要应用于方法的多个缓存操作。
  • @CacheConfig:设置类级别上共享的一些常见缓存设置。

@Cacheable注解

顾名思义,@Cacheable可以用来进行缓存的写入,将结果存储在缓存中,以便于在后续调用的时候可以直接返回缓存中的值,而不必再执行实际的方法。 最简单的使用方式,注解名称=缓存名称,使用例子如下:

  1.   @Cacheable("books")
  2. public Book findBook(ISBN isbn) {...}

一个方法可以对应两个缓存名称,如下:

  1. @Cacheable({"books", "isbns"})
  2. public Book findBook(ISBN isbn) {...} 

@Cacheable的缓存名称是可以配置动态参数的,比如选择传入的参数,如下: (以下示例是使用SpEL声明,如果您不熟悉SpEL,可以阅读Spring Expression Language)

  1. @Cacheable(cacheNames="books", key="#isbn")
  2. public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
  3.  
  4. @Cacheable(cacheNames="books", key="#isbn.rawNumber")
  5. public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
  6.  
  7. @Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")
  8. public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) 

@Cacheable还可以设置根据条件判断是否需要缓存

  • condition:取决于给定的参数是否满足条件
  • unless:取决于返回值是否满足条件

以下是一个简单的例子:

  1. @Cacheable(cacheNames="book", condition="#name.length() < 32")
  2. public Book findBook(String name)
  3.  
  4. @Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback")
  5. public Book findBook(String name) 

@Cacheable还可以设置:keyGenerator(指定key自动生成方法),cacheManager(指定使用的缓存管理),cacheResolver(指定使用缓存的解析器)等,这些参数比较适合全局设置,这里就不多做介绍了。

@CachePut注解

@CachePut:当需要更新缓存而不干扰方法的运行时 ,可以使用该注解。也就是说,始终执行该方法,并将结果放入缓存,注解参数与@Cacheable相同。 以下是一个简单的例子:

  1. @CachePut(cacheNames="book", key="#isbn")
  2. public Book updateBook(ISBN isbn, BookDescriptor descriptor) 

通常强烈建议不要对同一方法同时使用@CachePut和@Cacheable注解,因为它们具有不同的行为。可能会产生不可思议的BUG哦。

@CacheEvict注解

@CacheEvict:删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。这里还多了一个参数(allEntries),设置allEntries=true时,可以对整个条目进行批量删除。 以下是个简单的例子:

  1. @CacheEvict(cacheNames="books")
  2. public void loadBooks(InputStream batch)
  3.  
  4. //对cacheNames进行批量删除
  5. @CacheEvict(cacheNames="books", allEntries=true)
  6. public void loadBooks(InputStream batch) 

@Caching注解

@Caching:在使用缓存的时候,有可能会同时进行更新和删除,会出现同时使用多个注解的情况.而@Caching可以实现。 以下是个简单的例子:

  1. @Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
  2. public Book importBooks(String deposit, Date date) 

@CacheConfig注解

@CacheConfig:缓存提供了许多的注解选项,但是有一些公用的操作,我们可以使用@CacheConfig在类上进行全局设置。 以下是个简单的例子:

  1. @CacheConfig("books")
  2. public class BookRepositoryImpl implements BookRepository {
  3.  
  4. @Cacheable
  5. public Book findBook(ISBN isbn) {...}
  6. } 

可以共享缓存名称,统一配置KeyGenerator,CacheManager,CacheResolver。

实例

来看看我们在springboot中怎么使用redis来作为缓存吧.

为spring cache配置redis作为缓存

1.在pom.xml引入redis依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency> 

2.springboot集成redis配置文件(在本地启动的redis),在springboot中使用redis,只要配置文件写有redis配置,代码就可以直接使用了。

  1. spring:
  2. redis:
  3. database: 0 # Database index used by the connection factory.
  4. url: redis://user:@127.0.0.1:6379 # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:password@example.com:6379
  5. host: 127.0.0.1 # Redis server host.
  6. password: # Login password of the redis server.
  7. port: 6379 # Redis server port.
  8. ssl: false # Whether to enable SSL support.
  9. timeout: 5000 # Connection timeout. 

3.redis缓存配置类CacheConfig,这里对spring的缓存进行了配置,包括KeyGenerator,CacheResolver,CacheErrorHandler,CacheManager,还有redis序列化方式。

  1. /**
  2. * @author wwj
  3. */
  4. @Configuration
  5. public class CacheConfig extends CachingConfigurerSupport {
  6.  
  7. @Resource
  8. private RedisConnectionFactory factory;
  9.  
  10. /**
  11. * 自定义生成redis-key
  12. *
  13. * @return
  14. */
  15. @Override
  16. @Bean
  17. public KeyGenerator keyGenerator() {
  18. return (o, method, objects) -> {
  19. StringBuilder sb = new StringBuilder();
  20. sb.append(o.getClass().getName()).append(".");
  21. sb.append(method.getName()).append(".");
  22. for (Object obj : objects) {
  23. sb.append(obj.toString());
  24. }
  25. System.out.println("keyGenerator=" + sb.toString());
  26. return sb.toString();
  27. };
  28. }
  29.  
  30. @Bean
  31. public RedisTemplate<Object, Object> redisTemplate() {
  32. RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
  33. redisTemplate.setConnectionFactory(factory);
  34.  
  35. GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
  36.  
  37. redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);
  38. redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
  39.  
  40. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
  41. redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
  42. return redisTemplate;
  43. }
  44.  
  45. @Bean
  46. @Override
  47. public CacheResolver cacheResolver() {
  48. return new SimpleCacheResolver(cacheManager());
  49. }
  50.  
  51. @Bean
  52. @Override
  53. public CacheErrorHandler errorHandler() {
  54. // 用于捕获从Cache中进行CRUD时的异常的回调处理器。
  55. return new SimpleCacheErrorHandler();
  56. }
  57.  
  58. @Bean
  59. @Override
  60. public CacheManager cacheManager() {
  61. RedisCacheConfiguration cacheConfiguration =
  62. defaultCacheConfig()
  63. .disableCachingNullValues()
  64. .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
  65. return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
  66.  
  67. }
  68. } 

代码使用

测试@Cacheable方法

  1. @Test
  2. public void findUserTest() {
  3. for (int i = 0; i < 3; i++) {
  4. System.out.println("第" + i + "次");
  5. User user = userService.findUser();
  6. System.out.println(user);
  7. }
  8. }
  9.  
  10. @Override
  11. @Cacheable(value = {"valueName", "valueName2"}, key = "'keyName1'")
  12. public User findUser() {
  13. System.out.println("执行方法...");
  14. return new User("id1", "张三", "深圳", "1234567", 18);
  15. } 

执行结果

只有一次输出了'执行方法...',后面直接从缓存获取,不会再进入方法。

  1. 0
  2. 执行方法...
  3. User{id='id1', name='张三', address='深圳', tel='1234567', age=18}
  4. 1
  5. User{id='id1', name='张三', address='深圳', tel='1234567', age=18}
  6. 2
  7. User{id='id1', name='张三', address='深圳', tel='1234567', age=18}

测试@CachePut方法:对缓存进行了修改

  1. @Test
  2. public void updateUserTest() {
  3. userService.updateUser();
  4. User user = userService.findUser();
  5. System.out.println(user);
  6. }
  7.  
  8. @Override
  9. @CachePut(value = "valueName", key = "'keyName1'")
  10. public User updateUser() {
  11. System.out.println("更新用户...");
  12. return new User("id1", "李四", "北京", "1234567", 18);
  13. } 

执行结果

对缓存进行了更新,获取值的时候取了新的值

  1. 更新用户...
  2. User{id='id1', name='李四', address='北京', tel='1234567', age=18}

测试@CacheEvict方法:缓存被清空,再次findUser的时候又重新执行了方法。

  1. @Test
  2. public void clearUserTest() {
  3. userService.clearUser();
  4. User user = userService.findUser();
  5. System.out.println(user);
  6. }
  7.  
  8. @Override
  9. @CacheEvict(value = "valueName",allEntries = true)
  10. public void clearUser() {
  11. System.out.println("清除缓存...");
  12. } 

执行结果

这里清除了缓存,为什么还是没有执行方法呢?因为这个方法我们定了两个value值,清了一个还有一个

  1. 清除缓存...
  2. User{id='id1', name='张三', address='深圳', tel='1234567', age=18}

最后贴一下代码吧

User.java

  1. package com.wwj.springboot.model;
  2.  
  3. import java.io.Serializable;
  4.  
  5. /**
  6. * @author wwj
  7. */
  8. public class User implements Serializable {
  9.  
  10. public User() {
  11. }
  12.  
  13. private String id;
  14. private String name;
  15. private String address;
  16. private String tel;
  17. private Integer age;
  18.  
  19. //省略get,set,tostring
  20. }

CacheTest.java

  1. package com.wwj.springboot.cache;
  2.  
  3. import com.wwj.springboot.model.User;
  4. import com.wwj.springboot.service.UserService;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.cache.annotation.EnableCaching;
  9. import org.springframework.test.context.junit4.SpringRunner;
  10.  
  11. import javax.annotation.Resource;
  12.  
  13. /**
  14. * @author wwj
  15. */
  16. @RunWith(SpringRunner.class)
  17. @SpringBootTest
  18. @EnableCaching
  19. public class CacheTest {
  20.  
  21. @Resource
  22. private UserService userService;
  23.  
  24. @Test
  25. public void findUserTest() {
  26. for (int i = 0; i < 3; i++) {
  27. System.out.println("第" + i + "次");
  28. User user = userService.findUser();
  29. System.out.println(user);
  30. }
  31. }
  32.  
  33. @Test
  34. public void updateUserTest() {
  35. userService.updateUser();
  36. User user = userService.findUser();
  37. System.out.println(user);
  38. }
  39.  
  40. @Test
  41. public void clearUserTest() {
  42. userService.clearUser();
  43. User user = userService.findUser();
  44. System.out.println(user);
  45. }
  46.  
  47. }

UserService.java

  1. package com.wwj.springboot.service;
  2.  
  3. import com.wwj.springboot.model.User;
  4.  
  5. import java.util.List;
  6.  
  7. /**
  8. * @author wwj
  9. */
  10. public interface UserService {
  11.  
  12. /**
  13. * 获取用户
  14. * @return user
  15. */
  16. User findUser();
  17.  
  18. /**
  19. * 更新用户信息
  20. * @return user
  21. */
  22. User updateUser();
  23.  
  24. /**
  25. * 清除缓存的用户信息
  26. */
  27. void clearUser();
  28.  
  29. }

UserServiceImpl.java

  1. package com.wwj.springboot.service.impl;
  2.  
  3. import com.wwj.springboot.model.User;
  4. import com.wwj.springboot.service.UserService;
  5. import org.springframework.cache.annotation.CacheConfig;
  6. import org.springframework.cache.annotation.CacheEvict;
  7. import org.springframework.cache.annotation.CachePut;
  8. import org.springframework.cache.annotation.Cacheable;
  9. import org.springframework.stereotype.Service;
  10.  
  11. /**
  12. * @author wwj
  13. */
  14. @Service
  15. @CacheConfig(cacheNames = "CacheConfigName")
  16. public class UserServiceImpl implements UserService {
  17.  
  18. @Override
  19. @Cacheable(value = {"valueName", "valueName2"}, key = "'keyName1'")
  20. public User findUser() {
  21. System.out.println("执行方法...");
  22. return new User("id1", "张三", "深圳", "1234567", 18);
  23. }
  24.  
  25. @Override
  26. @CachePut(value = "valueName", key = "'keyName1'")
  27. public User updateUser() {
  28. System.out.println("更新用户...");
  29. return new User("id1", "李四", "北京", "1234567", 18);
  30. }
  31.  
  32. @Override
  33. @CacheEvict(value = "valueName",allEntries = true)
  34. public void clearUser() {
  35. System.out.println("清除缓存...");
  36. }
  37.  
  38. }

本文欢迎各位转载,但是转载文章之后必须在文章开头给出原文链接。感谢您的阅读,如果您觉得阅读本文对您有帮助,请点个“推荐”支持一下。

springboot整合spring @Cache和Redis的更多相关文章

  1. SpringBoot 结合 Spring Cache 操作 Redis 实现数据缓存

    系统环境: Redis 版本:5.0.7 SpringBoot 版本:2.2.2.RELEASE 参考地址: Redus 官方网址:https://redis.io/ 博文示例项目 Github 地址 ...

  2. 【快学SpringBoot】Spring Cache+Redis实现高可用缓存解决方案

    前言 之前已经写过一篇文章介绍SpringBoot整合Spring Cache,SpringBoot默认使用的是ConcurrentMapCacheManager,在实际项目中,我们需要一个高可用的. ...

  3. springboot 用redis缓存整合spring cache注解,使用Json序列化和反序列化。

    springboot下用cache注解整合redis并使用json序列化反序列化. cache注解整合redis 最近发现spring的注解用起来真的是很方便.随即产生了能不能吧spring注解使用r ...

  4. 【Spring】17、spring cache 与redis缓存整合

    spring cache,基本能够满足一般应用对缓存的需求,但现实总是很复杂,当你的用户量上去或者性能跟不上,总需要进行扩展,这个时候你或许对其提供的内存缓存不满意了,因为其不支持高可用性,也不具备持 ...

  5. SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理|前后端分离(下)----筑基后期

    写在前面 在上一篇文章<SpringBoot整合Shiro+MD5+Salt+Redis实现认证和动态权限管理(上)----筑基中期>当中,我们初步实现了SpringBoot整合Shiro ...

  6. Spring Boot(八)集成Spring Cache 和 Redis

    在Spring Boot中添加spring-boot-starter-data-redis依赖: <dependency> <groupId>org.springframewo ...

  7. springboot中使用cache和redis

    知识点:springboot中使用cache和redis (1)springboot中,整合了cache,我们只需要,在入口类上加 @EnableCaching 即可开启缓存 例如:在service层 ...

  8. 使用Spring Cache集成Redis

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...

  9. springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

随机推荐

  1. Your requirements could not be resolved to an installable set of packages

    使用composer下载laravel安装程序时(composer global require "laravel/installer"),报截图中的错误. 解决: 根据提示可知, ...

  2. Fiddler 抓包浅析

    Fiddler 工具浅析 Fiddler 是位于客户端和服务器端的 HTTP 代理,也是目前最常用的 HTTP 抓包工具之一.(Mac OS 建议采用 Charles) 它可以记录客户端和服务器之间的 ...

  3. [C++]linux下实现rm()函数删除文件或目录

    转载请注明原创:http://www.cnblogs.com/StartoverX/p/4600866.html 在linux下有两个函数可以用来删除文件: #include <unistd.h ...

  4. UNITY_资源路径与加载外部文件

    UNITY_资源路径与加载外部文件 https://www.tuicool.com/articles/qMNnmm6https://blog.csdn.net/appppppen/article/de ...

  5. python基础学习笔记(一)

    最好有点c++基础来看,,每天都更新一篇吧 这一篇是一些基础东西 1.运算符2.变量3.基本输入输出4.字符串5.列表6.元组7.字典8.集合9.简单的说下循环啥的 1.运算符 特别的 a / b:为 ...

  6. JAVA之访问控制符

    1.访问修饰符 public:该类和非该类的均能访问 protect:该类和该类的子类,同一个包内的成员也能访问 默认:同一个包内的类可以访问 private:只有该类可以访问 特性:在继承的关系中, ...

  7. Digitalocean + ss 搭建加密通信代理服务器

    本文以 DigitalOcean + ss/ssr 配置加密通道***为例,记录了手动搭梯子的过程. 启动一个服务器实例的操作可以参考我的这篇博文,这里主要介绍 ss/ssr 的服务搭建过程. 首先 ...

  8. NO.2:自学tensorflow之路------BP神经网络编程

    引言 在上一篇博客中,介绍了各种Python的第三方库的安装,本周将要使用Tensorflow完成第一个神经网络,BP神经网络的编写.由于之前已经介绍过了BP神经网络的内部结构,本文将直接介绍Tens ...

  9. Linux(Contos7.5)环境搭建之Gitblit安装(三)

    1.yum安装git(这一步暂时不清楚是否必要,因为在window上搭建并不需要)

  10. Python20 - Day09

    python并发编程之多线程理论 1.什么是线程? 进程只是用来把资源集中到一起(进程是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位. 多线程(多个控制线程)的概念是,在一个进程中存在 ...