Spring 缓存抽象示例详解

Spring缓存抽象概述

Spring框架自身并没有实现缓存解决方案,但是从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口,提供对缓存功能的声明,能够与多种流行的缓存实现集成。

Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;

Cache接口下Spring提供了各种xxxCache的实现:如RedisCache,EhCacheCache , ConcurrentMapCache等;

CacheManager接口为缓存管理器规范,简单来说就是用于存放cache,Spring默认也提供了一些列管理器的实现。

Spring缓存抽象提供了5个注解用来声明缓存规则:

@Cacheable:能够根据方法的请求参数对其结果进行缓存,多用于查询

@CachePut: 执行方法,并缓存结果

@CacheEvict:清空缓存

@Caching:能够同时应用多个缓存注解功能

@CacheConfig: 用于抽取缓存的公共配置(类级别)

以上5个注解除了@CacheConfig注解是类级别的注解,其余4个注解在类和方法上均可以使用,作用在类上表示对该类下所有方法生效,作用的方法上只对该方法生效,且只能用于public修饰的符方法,protected或者private修饰的方法不适用。

@Cacheable注解

@Cacheable注解的作用是Spring在调用该方法之前,首先在缓存中查找方法的返回值,默认的key是根据参数值生成,如果存在,直接返回缓存中的值,否则执行该方法,并将返回值保存到缓存中

@Cacheable运行流程:

1.方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;

(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。

2.去Cache中查找缓存的内容,使用一个key,默认就是方法的参数值;

key是按照某种策略生成的;默认是使用keyGenerator生成的,

     Spring默认加载的是SimpleCacheManage,SimpleKeyGenerator生成key的默认策略是:

如果没有参数;key=new SimpleKey()

如果有一个参数:key=参数的值

如果有多个参数:key=new SimpleKey(params)

3.没有查到缓存就调用目标方法;

4.将目标方法返回的结果,放进缓存中

@Cacheable属性说明:

  1.acheNames/value:该属性值必须提供,指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;

     如:cacheNames = "product"或者cacheNames = {"product1","product2"}

  2.key:缓存数据使用的key,不指定key则默认是使用方法参数的值该属性值支持SpEL表达式

3.cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器

4.condition:指定符合条件的情况下才缓存

  5.unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断

unless = "#result == null"

unless = "#a0==2":如果第一个参数的值是2,结果不缓存;

  6.sync:是否使用异步模式

使用示例:

@Cacheable(cacheNames = "product")// 默认key为参数,多个参数SimpleKey [arg1,arg2]
//@Cacheable(cacheNames = "product",key = "#root.methodName+'['+#id+']'")
//@Cacheable(cacheNames = "product",keyGenerator = "myKeyGenerator")
//@Cacheable(cacheNames = "product",key = "#root.methodName+'['+#id+']'",condition="#a0>10",unless = "#a0==11") //带条件的缓存满足condition=true缓存,满足unless=true则不缓存
public Product getProductById(Long id){
  Product product =productMapper.getProductById(id);
  System.out.println(product);
  return product;
}
//指定key属性值
@Cacheable(cacheNames ="product", key="#id")  //”#+参数名”的形式,直接使用参数名
//或者
//@Cacheable(cacheNames ="product", key="#a0")  //”#a+参数位置”的形式
  public Product getProductById(long id) {
   xxxx
  }
@Cacheable(cacheNames ="product", key="# productcondition.productId")
//或者
//@Cacheable(cacheNames ="product", key="#a0.productId")
  public Product getProduct (Product productcondition) {
   xxxx
  }

自定义Key生成器

除了通过SPEL表达式之外,还可以通过自定义key生成器的方式,Spring缓存模块提供了org.springframework.cache.interceptor.KeyGenerator接口用于缓存key的生成声明,因此我们可以自定义一个MyKeyGenerator类并实现了KeyGenerator接口 ,使用如下:

@Configuration
public class MyCacheConfig {
  @Bean("myKeyGenerator")
  public KeyGenerator keyGenerator(){
    return new KeyGenerator(){
      @Override
      public Object generate(Object target, Method method, Object... params) {
        return method.getName()+"["+ Arrays.asList(params).toString()+"]";
      }
    };
  }
}

该方法测试用,关于缓存key的生成方式,网上有很多种策略。

使用时只需要修改注解的key属性即可:

 @Cacheable(cacheNames = "product",keyGenerator = "myKeyGenerator")

 @CachePut

@CachePut注解的作用简单的说一句话:既调用方法,又缓存数据。@cachePut和@Cacheable两个注解都可以用于填充缓存,但使用上略有点差异,@Cacheable注解的执行流程是先在按key在缓存中查找,存在则返回,不存在则执行目标方法,并缓存目标方法的结果。而@CachePut并不会检查缓存,总是先执行目标方法,并将目标方法的结果保存到缓存中。实际中比如执行到更新操作时,则希望将最新的数据更新到缓存,如果该方法返回异常,将不再执行保存缓存的逻辑。

@CachePut属性说明

@CachePut注解属性与@CachePut类似,并没有增加其他属性

使用示例:

@CachePut(value="product",key = "#result.productId",condition = "#result!=null")
public Product updateProduct(Product product){
  int count = productMapper.updateProduct(product);
  System.out.println("影响行数:"+count);
  if(count>0){
    return product;
  }else{
    return null;
  }
}

@CacheEvict注解

该注解的作用根据指定的key或者是allEntries属性值移除缓存中特性的键值对。

@CacheEvict属性说明

与@Cacheable相比@CacheEvict注解提供了另外两个属性:

1.allEntries:表示是否清空所有缓存内容,默认false,如果该值为true则清空指定cacheNames缓存块下所有内容,如果指定了allEntries为true,那么再zhidingkey值将没有意义

2.beforeInvocation:是否在执行方法前请空缓存,默认值为false,如果该值为true则在调用目标方法前执行清空缓存,为false的情况下,如果目标方法抛出异常,则不再执行清空缓存逻辑

示例:

 //@CacheEvict(value="product",key="#id")
 //@CacheEvict(value="product",allEntries = true) //清楚所有缓存
 @CacheEvict(value="product",allEntries = true,beforeInvocation = true) //清楚所有缓存
 public boolean deleteProductById(Long id) {
   productMapper.deleteProductById(id);
   return true;
 }

@Caching注解

该注解是一个分组注解,作用是可以同时应用多个其他注解,该注解提供了3个属性cacheable,put,evict分别用于组合@Cacheable、@CachePut、@CacheEvict三个注解

使用示例:

@Caching(
     cacheable = {@Cacheable(value="product",key="#productName")},
     put = {
         @CachePut(value="product",key="#result.productId"),
         @CachePut(value="product",key="#result.productName")
     }
 )
 public Product getProductByName(String productName){
   Product product =productMapper.getProductByName(productName);
   return product;
 }

当@Cacheing同时含有CachePut注解和Cacheable注解时,仍然会先执行目标方法。(并不是按@Cacheable的执行过程,先检查缓存,存在则返回)

@CacheConfig

是一个类级别的注解,允许共享缓存的名称、KeyGenerator、CacheManager 和CacheResolver

示例:

@Service
 @CacheConfig(cacheNames = "product")
 public class ProductService {
 }

在类上使用该注解,指定cacheNames属性值,则类中方法上的注解将默认继承了该属性值,如果方法上注解使用和了@CacheConfig向同的属性,则以方法上的为准。

 @Service
 @CacheConfig(cacheNames = "product")
 public class ProductService {
   @Autowired
   private ProductMapper productMapper;
   @Cacheable(cacheNames = "product1",key = "#root.methodName+'['+#id+']'")
   public Product getProductById(Long id){
     Product product =productMapper.getProductById(id);
    System.out.println(product);
    return product;
   }
 }

上面@Cacheable和@CacheConfig都指定了属性值cacaeNames,实际以方法上注解指定的为准。

Spring缓存抽象的关键原理就是使用spring AOP,通过切面实现了在方法调用前、调用后获取方法的入参和返回值,进而实现了缓存的逻辑。

总结

以上所述是小编给大家介绍的Spring 缓存抽象示例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 实例详解Spring Boot实战之Redis缓存登录验证码

    本章简单介绍redis的配置及使用方法,本文示例代码在前面代码的基础上进行修改添加,实现了使用redis进行缓存验证码,以及校验验证码的过程. 1.添加依赖库(添加redis库,以及第三方的验证码库) <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency&

  • spring boot+spring cache实现两级缓存(redis+caffeine)

    spring boot中集成了spring cache,并有多种缓存方式的实现,如:Redis.Caffeine.JCache.EhCache等等.但如果只用一种缓存,要么会有较大的网络消耗(如Redis),要么就是内存占用太大(如Caffeine这种应用内存缓存).在很多场景下,可以结合起来实现一.二级缓存的方式,能够很大程度提高应用的处理效率. 内容说明: 缓存.两级缓存 spring cache:主要包含spring cache定义的接口方法说明和注解中的属性说明 spring boot

  • Spring Boot Web 静态文件缓存处理的方法

    采用Spring Boot + Freemarker开发Web项目时,由于一些静态文件比较大,如果是在PC上访问影响不大,当在手机上访问时,特别是用流量访问时速度会慢很多,而且很耗流量. 通过对请求进行抓包,可以发现每次进入一个页面都需要加载静态文件,如果不差钱的公司可以将静态文件放在CDN上来加快访问速度,或者用Nginx来做静态文件的缓存. 今天给大家介绍一种其他的缓存优化方式,通过Spring的缓存机制来缓存静态文件,在Spring Boot中配置静态文件缓存只需要在配置文件中加入下面的配

  • Spring Boot缓存实战 EhCache示例

    Spring boot默认使用的是SimpleCacheConfiguration,即使用ConcurrentMapCacheManager来实现缓存.但是要切换到其他缓存实现也很简单 pom文件 在pom中引入相应的jar包 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web<

  • SpringBoot项目中使用redis缓存的方法步骤

    本文介绍了SpringBoot项目中使用redis缓存的方法步骤,分享给大家,具体如下: Spring Data Redis为我们封装了Redis客户端的各种操作,简化使用. - 当Redis当做数据库或者消息队列来操作时,我们一般使用RedisTemplate来操作 - 当Redis作为缓存使用时,我们可以将它作为Spring Cache的实现,直接通过注解使用 1.概述 在应用中有效的利用redis缓存可以很好的提升系统性能,特别是对于查询操作,可以有效的减少数据库压力. 具体的代码参照该

  • 详解Spring boot使用Redis集群替换mybatis二级缓存

    1 . pom.xml添加相关依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.1.RELEASE</version> </parent> <!-- 依赖 --> <dependencies> &l

  • Spring 缓存抽象示例详解

    Spring缓存抽象概述 Spring框架自身并没有实现缓存解决方案,但是从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口,提供对缓存功能的声明,能够与多种流行的缓存实现集成. Cache接口为缓存的组件规范定义,包含缓存的各种操作集合: Cache接口下Spring提供了各种xxxCache的实现:如RedisCache,EhCacheCache , ConcurrentMapCa

  • spring结合hibernate示例详解

    单纯Hibernate程序 1.首先是导入hibernate的jar包. 2. 建立用户和用户操作记录实体,Log.Java和User.java.代码如下所示. Log.java import java.util.Date; public class Log { private int id; //日志的类别.日志一般起到一个不可否认性. //操作日志 安全日志 事件日志. private String type; private String detail; private Date time

  • Spring @value用法示例详解

    目录 一.两种使用方法 二.配置 2.1 @Value(“#{configProperties[‘key’]}”)使用 2.1.1配置文件: 2.2 @Value(“${key}”)使用 2.2.1 配置文件 为了简化读取properties文件中的配置值,spring支持@value注解的方式来获取,这种方式大大简化了项目配置,提高业务中的灵活性. 一.两种使用方法 1.@Value(“#{configProperties[‘key’]}”) 2.@Value(“${key}”) 二.配置 2

  • Shiro集成Spring之注解示例详解

    前言 Shiro的组件都是JavaBean/POJO式的组件,所以非常容易使用Spring进行组件管理,可以非常方便的从ini配置迁移到Spring进行管理,且支持JavaSE应用及Web应用的集成. 集成 Spring 后我们通过过滤器链来配置每个 URL 需要的权限,但当配置多了以后就会不方便,而且只支持 URL 级别的配置. 好在 Shiro 提供了相应的注解用于权限控制,此处使用了 Spring MVC 来测试Shiro注解,当然 Shiro 注解不仅仅可以在 web 环境使用,在独立的

  • Vue的缓存方法示例详解

    最近新做了个需求"前端缓存" 需求背景:解决表单高频率重复填报问题,要求打开页面自动填充上次录入的数据,数据存储期限为一周(7天有效期). 说起缓存首先想到的则是 localstorage.sessionStorage sessionStorage 也称会话缓存,当用户关闭浏览器窗口后,数据就会被删除: sessionStorage.setItem("key","value");//存储 sessionStorage.getItems("

  • 手动实现Redis的LRU缓存机制示例详解

    前言 最近在逛博客的时候看到了有关Redis方面的面试题,其中提到了Redis在内存达到最大限制的时候会使用LRU等淘汰机制,然后找了这方面的一些资料与大家分享一下. LRU总体大概是这样的,最近使用的放在前面,最近没用的放在后面,如果来了一个新的数,此时内存满了,就需要把旧的数淘汰,那为了方便移动数据,肯定就得使用链表类似的数据结构,再加上要判断这条数据是不是最新的或者最旧的那么应该也要使用hashmap等key-value形式的数据结构. 第一种实现(使用LinkedHashMap) pub

  • SpringBoot集成本地缓存性能之王Caffeine示例详解

    目录 引言 Spring Cache 是什么 集成 Caffeine 核心原理 引言 使用缓存的目的就是提高性能,今天码哥带大家实践运用 spring-boot-starter-cache 抽象的缓存组件去集成本地缓存性能之王 Caffeine. 大家需要注意的是:in-memeory 缓存只适合在单体应用,不适合与分布式环境. 分布式环境的情况下需要将缓存修改同步到每个节点,需要一个同步机制保证每个节点缓存数据最终一致. Spring Cache 是什么 不使用 Spring Cache 抽象

  • Spring Cloud动态配置刷新RefreshScope使用示例详解

    目录 引言 一.了解@RefreshScope,先要了解@Scope 二.RefreshScope 的实现原理 三.使用——@RefreshScope 使用流程 引言 用过Spring Cloud的同学都知道在使用动态配置刷新的我们要配置一个 @RefreshScope,在类上才可以实现对象属性的的动态更新. @RefreshScope 能实现动态刷新全仰仗着 @Scope这个注解. 一.了解@RefreshScope,先要了解@Scope 1.RefreshScope继承于GenericSco

  • Spring实现泛型注入的示例详解

    目录 1.Spring泛型注入 2. 关于java泛型有四种Type GenericArrayType泛型数组类型 ParameterizedType参数化类型 TypeVariable 类型变量 WildcardType 通配符类型 1.Spring泛型注入 创建一个抽象泛型类BaseDao,有参数化类型T public abstract class BaseDao<T> { public abstract void eat(); } 每种动物有不同的行为,猫.狗 public class

  • Spring依赖注入(DI)两种方式的示例详解

    目录 一.依赖注入方式 二.setter注入 引用类型 简单类型 三.构造器注入 引用类型 简单类型 参数适配(了解) 四.依赖注入方式选择 一.依赖注入方式 思考:向一个类中传递数据的方式有几种? 普通方法(set方法) 构造方法 思考:依赖注入描述了在容器中建立bean与bean之间依赖关系的过程,如果bean运行需要的是数字或字符串呢? 引用类型 简单类型(基本数据类型与String) 依赖注入方式: setter注入 简单类型 引用类型 构造器注入 简单类型 引用类型 二.setter注

随机推荐