Spring Cache 整体认识

Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。

Spring 的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如 EHCache 集成。特点如下:

1、开箱即用,不需要自身添加过多的代码

2、注解驱动,使用方便

3、和业务代码做到了隔离,互相不污染

4、可以自定义缓存管理器、缓存,做到了第三方框架的良好融合;并且可以同时融合多个缓存框架

为了大家能更加直观的了解到之前和使用后的区别,我们对之前的代码和现在的做下对比:

之前的代码如下:

package oldcache; 
 
import cacheOfAnno.Account; 
 
public class MyAccountService { 
  private MyCacheManager<Account> cacheManager; 
  
  public MyAccountService() { 
    cacheManager = new MyCacheManager<Account>();// 构造一个缓存管理器
  } 
  
  public Account getAccountByName(String acctName) { 
    Account result = cacheManager.getValue(acctName);// 首先查询缓存
    if(result!=null) { 
      System.out.println("get from cache..."+acctName); 
      return result;// 如果在缓存中,则直接返回缓存的结果
    } 
    result = getFromDB(acctName);// 否则到数据库中查询
    if(result!=null) {// 将数据库查询的结果更新到缓存中
      cacheManager.addOrUpdateCache(acctName, result); 
    } 
    return result; 
  } 
  
  public void reload() { 
    cacheManager.evictCache(); 
  } 
  
  private Account getFromDB(String acctName) { 
    System.out.println("real querying db..."+acctName); 
    return new Account(acctName); 
  } 
}

通过上面的代码,我们可以看到整个的缓存逻辑和业务逻辑混合在一起,代码互相污染。

使用Spring Cache 框架后,代码的整体风格如下:

package cacheOfAnno; 
 
import org.springframework.cache.annotation.CacheEvict; 
import org.springframework.cache.annotation.Cacheable; 
 
public class AccountService { 
  @Cacheable(value="accountCache",key = "#userName")// 使用了一个缓存名叫 accountCache 
  public Account getAccountByName(String userName) { 
    // 方法内部实现不考虑缓存逻辑,直接实现业务
    System.out.println("real query account."+userName); 
    return getFromDB(userName); 
  } 
  
  private Account getFromDB(String acctName) { 
    System.out.println("real querying db..."+acctName); 
    return new Account(acctName); 
  } 
}

 可以看到,代码更加干净,并且代码逻辑清楚。由于Spring Cache框架为注解驱动的,那么我讲对其注解进行一一说明

序号 注解名称 作用
1   Cacheable 将方法的执行结果放到缓存中。下次执行时,若是发现有缓存,则直接取缓存中的数据      
2 CachePut 将方法的执行结果放到缓存中    
3 CacheEvict   移除指定的缓存
4 CacheConfig      配置信息
5 Cacheing 可以指定各种类型的注解
6 自定义注解  

注解介绍

1、Cacheable  --- 参数介绍

  • cacheNames  :指定缓存名称
  • key: 保存的键
  • condition:条件。若是满足条件,则保存
  • unless: 否决条件,方法执行完毕后验证,为false的时候,才保存
  • cacheManger: 指定cache管理器
  • cacheResolver: 按照指定的名称分析得到cache
  • sync: 为true,表明若是多个线程调用此方法,只有一个线程可以访问,其他线程直接从缓存中获取。
  • keyGenerator:键的生成器

2、CachePut

  • cacheNames:缓存名称
  • key:对应的键
  • condition:条件。同上
  • unless:同上
  • keyGenerator:同上
  • cacheResolver:同上

3、CacheEvict

  • cacheNames:缓存名称
  • key:对应的键
  • condition:条件。同上
  • unless:同上
  • keyGenerator:同上
  • cacheResolver:同上
  • allEntries:是否全部情况
  • beforeInvocation:是否在方法之前执行;若为false,不保证,能执行(例外:若是方法报异常)

4、CacheConfig:配置 。主要是配置在类上

  • cacheNames:缓存的名称
  • cacheManager:缓存管理器
  • keyGenerator:键生成器
  • cacheResolver:cache分析器

SPEL说明

Cache框架中的key、condition、unless中的表达式是按照SPEL的形式进行描述的,下面将对其中的参数进行一一说明:

序号 name location 描述

示例

1 methodName root 当前被调用的方法的名称 #root.methodName
2 method root 当前被调用的方法 #root.method
3 target root 当前被调用的实体 #root.target
4 targetClass root 当前被调用的实体的类型 #root.targetClass
5 args Evaluation context 当前被调用方法的参数 #root.args[0]
6 caches root 当前被调用方法的缓存集合 #root.caches[0].name
7 result Evaluation context

当前被调用方法的返回值,只能在unless 或是

方法执行完毕的逻辑中使用

#result
8 Argument name Evaluation context 当前方法的参数名称

#userName  #p[0]  #a[0]

 

 

 

 

 

 

 

 

 

 

 

示例如下:

@Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback == null")
public Optional<Book> findBook(String name)

 

posted @ 2020-04-24 18:50  一家人  阅读(276)  评论(0编辑  收藏  举报