Spring缓存注解

来源:互联网 发布:淘宝网络兼职可信吗 编辑:程序博客网 时间:2024/06/06 01:29

概述

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

 

缓存的注解有以下三个

 

@Cancheable@CancheEvict @CachePut

 

引用缓存

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


注意,此类的getAccountByName方法上有一个注释 annotation,即 @Cacheable(value=”accountCache”),这个注释的意思是,当调用这个方法的时候,会从一个名叫 accountCache 的缓存中查询,如果没有,则执行实际的方法(即查询数据库),并将执行的结果存入缓存中,否则返回缓存中的对象。这里的缓存中的 key就是参数userNamevalue就是Account对象。“accountCache”缓存是在 spring*.xml中定义的名称。

 

 <beansxmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:cache="http://www.springframework.org/schema/cache"xmlns:p="http://www.springframework.org/schema/p"  xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd     http://www.springframework.org/schema/cache     http://www.springframework.org/schema/cache/spring-cache.xsd">      <cache:annotation-driven />    <bean id="accountServiceBean"class="cacheOfAnno.AccountService"/>     <!-- generic cache manager -->   <bean id="cacheManager"  class="org.springframework.cache.support.SimpleCacheManager">     <property name="caches">       <set>         <bean          class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"           p:name="default" />                <bean          class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"           p:name="accountCache"/>       </set>     </property>   </bean> </beans>


spring 配置文件有一个关键的支持缓存的配置项:<cache:annotation-driven />,这个配置项缺省使用了一个名字叫 cacheManager 的缓存管理器,这个缓存管理器有一个 spring的缺省实现,即org.springframework.cache.support.SimpleCacheManager,这个缓存管理器实现了我们刚刚自定义的缓存管理器的逻辑,它需要配置一个属性 caches,即此缓存管理器管理的缓存集合,除了缺省的名字叫 default的缓存,我们还自定义了一个名字叫accountCache的缓存,使用了缺省的内存存储方案 ConcurrentMapCacheFactoryBean,它是基于 java.util.concurrent.ConcurrentHashMap 的一个内存缓存实现方案。

 

清空缓存


有了缓存的实现,我们还得清空缓存

为了加入清空缓存的逻辑,我们只要对 AccountService.java 进行修改,从业务逻辑的角度上看,它有两个需要清空缓存的地方

当外部调用更新了账号,则我们需要更新此账号对应的缓存

当外部调用说明重新加载,则我们需要清空所有缓存

package cacheOfAnno;  importorg.springframework.cache.annotation.CacheEvict; importorg.springframework.cache.annotation.Cacheable;  public class AccountService {   @Cacheable(value="accountCache")//使用了一个缓存名叫 accountCache   public Account getAccountByName(StringuserName) {     // 方法内部实现不考虑缓存逻辑,直接实现业务     return getFromDB(userName);   }  @CacheEvict(value="accountCache",key="#account.getName()")//清空 accountCache 缓存   public void updateAccount(Account account) {     updateDB(account);   }   @CacheEvict(value="accountCache",allEntries=true)// 清空 accountCache 缓存   public void reload() {   }    private Account getFromDB(String acctName) {     System.out.println("real queryingdb..."+acctName);     return new Account(acctName);   }    private void updateDB(Account account) {     System.out.println("real updatedb..."+account.getName());   }  }

按条件操作缓存

 

前面介绍的缓存方法,没有任何条件,即所有对 accountService 对象的 getAccountByName方法的调用都会起动缓存效果,不管参数是什么值,如果有一个需求,就是只有账号名称的长度小于等于 4 的情况下,才做缓存,大于 4 的不使用缓存,那怎么实现呢?

Springcache 提供了一个很好的方法,那就是基于 SpEL 表达式的 condition 定义,这个condition 是 @Cacheable 注释的一个属性,下面我来演示一下

 

AccountService.java(getAccountByName方法修订,支持条件) @Cacheable(value="accountCache",condition="#userName.length()<= 4")// 缓存名叫 accountCache public Account getAccountByName(StringuserName) { // 方法内部实现不考虑缓存逻辑,直接实现业务 return getFromDB(userName); }

其中的 condition=”#userName.length() <=4”,这里使用了 SpEL 表达式访问了参数 userName对象的 length() 方法,条件表达式返回一个布尔值,true/false,当条件为 true,则进行缓存操作,否则直接调用方法执行的返回结果

 

小结:

 

注解驱动能极大减少我们编写常见缓存代码量,通过少量标签和配置文件,可达到代码具备缓存的效果,灵活性很好。



2 1