Spring Cache的基础

Spring Cache
文章目录

  • Spring Cache
    • 一、认识`Spring Cache`
    • 二、Spring Cache 抽象
      • 2.1 缓存注解
        • (1)`@Cacheable`
        • (2)`@CachePut`
        • (4)`@Caching`
        • (5) `@CacheConfig` 类级别的缓存
    • 三、实践经验

一、认识Spring Cache 第一步:配置缓存管理
>

【Spring Cache的基础】第二步:使用缓存
@Cacheable(cacheNames = "users") @Override public User getUserById(String userId) { System.out.println("real query user." + userId); return getFromDB(userId); }private User getFromDB(String userId){ System.out.println("real querying db..." + userId); return new User.Builder().userId(userId).email("someone@gmail.com").builder(); }

二、Spring Cache 抽象 只有使用public定义的方法才可以被缓存。
缓存的本质就是键/值对集合。在默认情况下,缓存抽象使用方法签名及参数值作为一个键值,并将该键与方法调用的结果组成键/值对。
2.1 缓存注解
(1)@Cacheable
Spring首先在缓存中查找数据,如果没有则执行方法并缓存结果,然后返回数据
  • 缓存名必须提供;可以使用引号、Value或者cacheNames属性来定义名称
    @Cacheable(cacheNames = "users") @Cacheable(values = "users") @Cacheable(cacheNames = {"cache01","cache02"})

  • 键生成器
    默认情况下,缓存抽象使用方法签名及参数值作为一个键值,并将键与方法调用的结果组成键/值对。
    1)可以使用SpEL指定自定义键
    @Cacheable(cacheNames = "users", key = "#user.userCode") public User getUserByUser(User user) { System.out.println("real query user." + user.getUserCode()); return getFromDB(user.getUserId()); }

    2)可以通过实现org.springframework.cache.interceptor.KeyGenerator接口来定义个性化的Key生成器
    @Cacheable(cacheNames = "users", keyGenerator = "myKeyGenerator")

    3)带条件缓存
    @Cacheable(cacheNames = "users", key = "#user.userCode", condition = "#user.age >= 12")

(2)@CachePut
首先执行方法,然后将返回值放入缓存。当希望使用方法返回值更新缓存时,便可以选择这种方法。
####(3)@CacheEvict
负责从给定的缓存中移除一个值。
默认情况下,@CacheEvict注解在方法调用之后运行。
@allEntries属性 定义了是否移除缓存的所有条目,默认不移除这些条目;@beforeInvocation属性定义了在调用方法之前还是之后完成移除操作。
@CacheEvict(cacheNames = "users", allEntries = true, beforeInvocation = true)

(4)@Caching @Caching是一个组注解,可以为一个方法定义提供基于@Cacheable@CacheEvict@CachePut注解的数组
@Caching(cacheable = {@Cacheable(value = "https://www.it610.com/article/members", condition = "#obj instanceof T(com.hef.domain.Member)"), @Cacheable(value = "https://www.it610.com/article/visitors", condition = "#obj instanceof T(com.hef.domain.Visitor)")})

(5) @CacheConfig 类级别的缓存 如果一个类中需要缓存的方法注解属性都相似,可以在类上通过@CacheConfig配置缓存,在方法上用@Cacheable标记。
三、实践经验 基于Proxy的Spring AOP带来的内部调用问题。
如果对象的方法是内部调用(this)而不是外部引用,则会导致代理失效,那么切面就失效,也就是说上面定义的各种注解,包括@Cacheable、@CachePut、@CacheEvict都会失效
public User getUserByUser02(User user) { return getUserByUser(user); }@Cacheable(cacheNames = "users", key = "#user.userCode") public User getUserByUser(User user) { System.out.println("real query user." + user.getUserCode()); return getFromDB(user.getUserId()); }

在方法getUserByUser02()上调用getUserByUser(),发生了内部调用(this),所以没有使用代理类,导致Spring Cache失效。要避免这个问题,就要避免方法的内部调用,或者避免使用基于代理的AOP模式,也可以使用基于AspectJ的AOP模式来解决这个问题。

    推荐阅读