spring cache 中guava CacheBuilder的个性实例化

spring cache在4.0以上版本正式对guava cache进行集成,相应的 CacheManager实现类:

org.springframework.cache.guava.GuavaCacheManager

要求google guava 12.0 或以上版本.

spring cache中guava cache默认使用方式

在spring 的xml文件中进行如下配置:

<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.guava.GuavaCacheManager" />

然后就可以使用spring cache 注解@cacheable @cacheput @cacheEvict 等进行方法级的缓存操作。

默认使用的问题

默认的实现方式对于缓存的内容是没有过期限制的,这个实现结果与使用ConcurrentMapCache没有什么质的区别。这种使用方式将guava cache的优势全都抹杀了。所以我们需要个性化实例化CacheBuilder,设置我们需要属性值,比如写入5秒过期等特性。

在GuavaCacheManager中有三个方法可供我们使用(copy自spring 4.2.x版本)

public void setCacheBuilder(CacheBuilder<Object, Object> cacheBuilder) {
    Assert.notNull(cacheBuilder, "CacheBuilder must not be null");
    doSetCacheBuilder(cacheBuilder);
}


public void setCacheBuilderSpec(CacheBuilderSpec cacheBuilderSpec) {
    doSetCacheBuilder(CacheBuilder.from(cacheBuilderSpec));
}


public void setCacheSpecification(String cacheSpecification) {
    doSetCacheBuilder(CacheBuilder.from(cacheSpecification));
}

这三个方法为我们提供了三个方案来进行个性实例化guava的CacheBuilder。

优化方案1 public void setCacheBuilder(CacheBuilder

优化方案2 public void setCacheBuilderSpec(CacheBuilderSpec cacheBuilderSpec)

首先简单介绍一下com.google.common.cache.CacheBuilderSpec,简单来说它就是CacheBuilder的配置类。

关于CacheBuilderSpecr的文档说明(copy自guava 18.0版本):

<p>{@code CacheBuilderSpec} supports parsing configuration off of a string, which makes it
  especially useful for command-line configuration of a {@code CacheBuilder}.

  <p>The string syntax is a series of comma-separated keys or key-value pairs, each corresponding
  to a {@code CacheBuilder} method.
  <ul>
  <li>{@code concurrencyLevel=[integer]}: sets {@link CacheBuilder#concurrencyLevel}.
  <li>{@code initialCapacity=[integer]}: sets {@link CacheBuilder#initialCapacity}.
  <li>{@code maximumSize=[long]}: sets {@link CacheBuilder#maximumSize}.
  <li>{@code maximumWeight=[long]}: sets {@link CacheBuilder#maximumWeight}.
  <li>{@code expireAfterAccess=[duration]}: sets {@link CacheBuilder#expireAfterAccess}.
  <li>{@code expireAfterWrite=[duration]}: sets {@link CacheBuilder#expireAfterWrite}.
  <li>{@code refreshAfterWrite=[duration]}: sets {@link CacheBuilder#refreshAfterWrite}.
  <li>{@code weakKeys}: sets {@link CacheBuilder#weakKeys}.
  <li>{@code softValues}: sets {@link CacheBuilder#softValues}.
  <li>{@code weakValues}: sets {@link CacheBuilder#weakValues}.
  <li>{@code recordStats}: sets {@link CacheBuilder#recordStats}.
  </ul>

  <p>The set of supported keys will grow as {@code CacheBuilder} evolves, but existing keys will
  never be removed.

  <p>Durations are represented by an integer, followed by one of "d", "h", "m", or "s",
  representing days, hours, minutes, or seconds respectively. (There is currently no syntax to
  request expiration in milliseconds, microseconds, or nanoseconds.)

  <p>Whitespace before and after commas and equal signs is ignored. Keys may not be repeated; it is
  also illegal to use the following pairs of keys in a single value:
  <ul>
  <li>{@code maximumSize} and {@code maximumWeight}
  <li>{@code softValues} and {@code weakValues}
  </ul>

  <p>{@code CacheBuilderSpec} does not support configuring {@code CacheBuilder} methods with
  non-value parameters. These must be configured in code.

简单来说,该类可以通过配置字符串来生成CacheBuilder,字符串的规则:

属性=值及单位(如果需要单位),比如
expireAfterWrite=10s即写后10秒即过期
单位现在只支持 "d", "h", "m", or "s" 分别为天,小时,分,秒,目前只支持这四个单位,其他暂不支持;
多个属性用英文逗号(,) 分隔;

但是关于CacheBuilderSpec的实例化依然是采用静态方法的,所以也只能采用工厂模式进行实例化,然后注入GuavaCacheManager。这个过程与方案1差不多,不多介绍了。这个方案也太重,不好。

优化方案3 public void setCacheSpecification(String cacheSpecification)

现在理解这个方法就很容易了,因为它是方案2的包装,我们只需要传入符合创建CacheBuilder的字符串,它就会将相应的字符串转交给CacheBuilderSpec,来创建我们需要个性化CacheBuilder实例了.只是这里只需要传入相应的字符串,而不是CacheBuilderSpec使用方式

在spring 的xml文件中配置如下bean

<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.guava.GuavaCacheManager" >
    <property name="cacheSpecification" value="expireAfterWrite=10s,initialCapacity=100" />
</bean>

这个方案不需要重写代码,即通过配置就可以解决问题,但是需要了解CacheBuilder的实例化原理。所以有的时候,了解代码的实现原理非常重要的。

猜你喜欢

转载自blog.csdn.net/zhurhyme/article/details/77341808
今日推荐