关于@Cacheable

对于一些经常访问,却又很少变动的类常量列表,每调用一次,都会增加一次数据库IO访问,缓存是个不错的策略。

@Cacheable可以标记在一个方法上,也可以标记在一个类上。
当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略,这个稍后会进行说明。需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。

@Cacheable的三个属性,value、key和condition。
1.1.1 value属性指定Cache名称

value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

   @Cacheable("cache1")//Cache是发生在cache1上的

   public User find(Integer id) {

      returnnull;

   }

  @Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的

   public User find(Integer id) {

      returnnull;

   }
1.1.2 使用key属性自定义key

key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。我们这里先来看看自定义策略,至于默认策略会在后文单独介绍。

自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。下面是几个使用参数作为key的示例。

  @Cacheable(value="users", key="#id")

   public User find(Integer id) {

      returnnull;

   }


   @Cacheable(value="users", key="#p0")

   public User find(Integer id) {

      returnnull;

   }

   @Cacheable(value="users", key="#user.id")

   public User find(User user) {

      returnnull;

   }


   @Cacheable(value="users", key="#p0.id")

   public User find(User user) {

      returnnull;

   }

除了上述使用方法参数作为key之外,Spring还为我们提供了一个root对象可以用来生成key。通过该root对象我们可以获取到以下信息。

属性名称描述示例
methodName当前方法名#root.methodName
method当前方法#root.method.name
target当前被调用的对象#root.target
targetClass当前被调用的对象的class#root.targetClass
args当前方法参数组成的数组#root.args[0]
caches当前被调用的方法使用的Cache#root.caches[0].name

当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:

   @Cacheable(value={"users", "xxx"}, key="caches[1].name")

   public User find(User user) {

      returnnull;

   }
1.1.3 condition属性指定发生的条件

有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当user的id为偶数时才会进行缓存。

   @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")

   public User find(User user) {

      System.out.println("find user by user " + user);

      return user;

   }
1.1.4 unless属性是指当满足条件时不缓存

最常用的就是当返回结果为空时,不采取缓存策略。

    @Override
    @Cacheable(value = "allPartner",unless = "#result == null")
    public List<CooperativePartnerInfo> getPartner() {
        return cooperativePartnerMapper.getEcPartnerList();
    }
二、@Cacheable的缓存位置

若不进行任何配置,默认缓存为concurrentMap,若.properties文件里配置了redis,则缓存在redis里,若想采用ehcache,配置ehcache.xml与resources目录下,然后再.approperties指定spring.cache.ehcache.config=ehcache.xml即可。

ehcache配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
    <!--<diskStore path="logs/ehcache"/>-->

    <!-- 设定缓存的默认数据过期策略 -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="10"
            timeToLiveSeconds="20"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"/>

    <cache name="cp_salary:cache:10m"
           maxElementsInMemory="100000"
           eternal="false"
           overflowToDisk="false"
           timeToIdleSeconds="10"
           timeToLiveSeconds="600"/>

    <cache name="cp_salary:cache:20m"
           maxElementsInMemory="100000"
           eternal="false"
           overflowToDisk="false"
           timeToIdleSeconds="10"
           timeToLiveSeconds="1200"/>

    <cache name="cp_salary:cache:30m"
           maxElementsInMemory="100000"
           eternal="false"
           overflowToDisk="false"
           timeToIdleSeconds="10"
           timeToLiveSeconds="1800"/>

</ehcache>

三、若想两种或者同时多种切换使用,参考:

http://www.cnblogs.com/fashflying/p/6908028.html
https://blog.csdn.net/s674334235/article/details/82593899,相信会有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值