您的位置:首页 > 编程语言 > Java开发

Spring缓存注解

2016-01-01 16:33 465 查看

概述

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
就是参数userName,value
就是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,则进行缓存操作,否则直接调用方法执行的返回结果

小结:

注解驱动能极大减少我们编写常见缓存代码量,通过少量标签和配置文件,可达到代码具备缓存的效果,灵活性很好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: