@Cache源码分析

Scroll Down

介绍

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

Spring 的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如 EHCache 集成。

其特点总结如下:

  • 通过少量的配置 annotation 注释即可使得既有代码支持缓存
  • 支持开箱即用 Out-Of-The-Box,即不用安装和部署额外第三方组件即可使用缓存
  • 支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的 key 和 condition
  • 支持 AspectJ,并通过其实现任何方法的缓存支持
  • 支持自定义 key 和自定义缓存管理者,具有相当的灵活性和扩展性

使用

EnableCaching

开启spring注解驱动的cache管理能力,类似于spring xml命名空间cache:*的支持。将会和org.springframework.context.annotation.Configuration一起使用。
在上述的场景中,@EnableCaching和cache:annotation-driven/负责注册spring所需的管理注解驱动的cache管理组件,如org.springframework.cache.interceptor.CacheInterceptor,当org.springframework.cache.annotation.Cacheable方法触发时基于proxy-或者基于AspectJ的advice 会将interceptor织入调用栈中。

  必须注册org.springframework.cache.CacheManager类型的bean,原因是框架没有默认的可用。不同点在于cache:annotation-driven元素假定了一个名称为cacheManager的bean,而@EnableCaching通过类型检索一个cache manage bean。因此cache manager bean方法的命名不是显式的。

  如果希望使用一种@EnableCaching与cache manager bean更直接的方式,spring提供了CachingConfigurer回调接口的实现,注意实现语句和@override注解方法
注意,上述示例中的keyGenerator方法,它允许自定义一个cache key产生策略。每个spring的org.springframework.cache.interceptor.KeyGenerator spi,通常将配置spring的org.springframework.cache.interceptor.SimpleKeyGenerator,一个key生成器必须显示指明。如果不需要定制,则直接返回new SimpleKeyGenerator()。

boolean proxyTargetClass() default false;

表明是创建基于子类代理(cglib)还是基于接口的标准java代理,默认是false。当且仅当mode()设置成Advice#PROXY时其作用。

注意,这个属性设置为true时会影响到所有spring管理bean的代理,而不仅仅是被标识为@Cacheable的接口或者类。例如,spring标注的其它bean如@Transactional将会同时升级到子类代理。这种方式实际上没有负面影响,除非显示期望一种代理类型,例如测试。

  • @Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
  • @CachePut 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
  • @CachEvict 主要针对方法配置,能够根据一定的条件对缓存进行清空

@Cacheable、@CachePut、@CacheEvict 注释介绍

通过上面的源码,我们可以看到 spring cache 主要使用两个注释标签,即 @Cacheable、@CachePut 和 @CacheEvict,我们总结一下其作用和配置方法。

@Cacheable 作用和配置方法

@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@Cacheable 主要的参数

参数名参数说明例子
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

@CachePut 作用和配置方法

@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
@CachePut 主要的参数

参数名参数说明例子
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

@CacheEvict 作用和配置方法

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空
@CacheEvict 主要的参数

参数名参数说明例子
value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:@Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
allEntries是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存例如:@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存例如:@CachEvict(value=”testcache”,beforeInvocation=true)