【Spring Cache】二 Spring 缓存操作相关注解及属性

前言

本章节了解一下 Spring 定义的缓存相关注解 @Cacheable @CachePut @CacheEvict @Caching @CacheConfig,并了解相关属性

@Cacheable

/**
 * Cacheable 表明开启缓存行为,如果标注类上就表示缓存所有方法
 * 缓存 key 基于参数生成,也可以指定 SpEL 表达式,或者自定义 KeyGenerator
 * 如果没有获取到缓存结果,就将方法执行的结果缓存进去,如果方法返回值类型为
 * 		Optional,缓存的会是实际值
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable {

	@AliasFor("cacheNames")
	String[] value() default {};

	// 用于匹配缓存的目标 cache name
	@AliasFor("value")
	String[] cacheNames() default {};

	/**
	 * 支持 SpEL 表达式指定 key,默认为空,则基于 keyGenerator 生成,
	 * 		若未指定 keyGenerator,则基于参数生成
	 * SpEL 的 context 提供如下参数
	 * 		#root.method:目标方法
	 * 		#root.target:目标对象
	 * 	    #root.caches:目标 Cache
	 * 	    #root.methodName:方法名称简写
	 * 	    #root.targetClass:目标 Class
	 * 	    目标参数的获取有:#root.args[1] || #p1 || #a1
	 */
	String key() default "";

	// 自定义 KeyGenerator 的 beanName,与 key 属性互斥
	String keyGenerator() default "";

	// 如果没有指定 cacheResolver,则基于这个 CacheManager 的 beanName 获取
	// 与 cacheResolver	属性互斥
	String cacheManager() default "";

	// 自定义 CacheResolver 的 beanName
	String cacheResolver() default "";

	// 基于 SpEL 的 条件表达式,指定缓存触发的条件,默认为空,即无条件触发
	String condition() default "";

	/**
	 * 基于 SpEL 对方法执行结果的缓存条件判断
	 * 默认为空意味着无条件缓存结果
	 * 在之前 context 的基础上还可以访问
	 * 		#result:方法执行结果,对于Optional 返回值它获取的是实际值
	 */
	String unless() default "";

	/**
	 * 表明目标方法是否在并发环境下支持同步操作,开启时受到如下限制:
	 * 1)不支持 unless 属性
	 * 2)只能针对一个缓存,由 cacheNames 属性指定
	 * 3)不支持同时有其他操作,或者多个 Cacheable 合并
	 * 但究竟是否支持缓存同步其实还是取决于底层供应商的实现
	 */
	boolean sync() default false;

}
  • 如果标注在类上则标识所有方法,如果标注在方法上则标识目标方法,开启缓存操作
  • 该缓存操作会在执行目标方法前先从目标缓存中获取,获取不到才会执行目标方法,然后将结果缓存
  • 提供了大量属性:
    • value & cacheNames:用于匹配缓存目标 Cachename
    • key & keyGenerator:用于解析 cacheKeykey 属性允许指定一个 SpEL 表达式来计算 cacheKey,如果未指定则会基于自定义的 keyGenerator 生成,如果都没有则会基于参数生成,不难理解 keykeyGenerator 是互斥的
    • cacheManager & cacheResolver:也是一对互斥的属性,当未提供 cacheResolver 时会尝试基于 cacheManager 解析对应的 cacheResolver
    • condition & unless:基于 SpEL 计算的条件表达式,区别是后者基于方法返回值决定是否缓存,因此其 Expression Context 中额外包含 #result 变量
    • sync:表示是否支持同步操作,最终由具体的 Provider 提供支持

@CachePut

/**
 * 缓存目标类上所有或指定方法
 * 与 @Cacheable 不同的是,只要满足 condition & unless 就触发,
 * 		而不会先去目标 Cache 查一遍
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CachePut {

	@AliasFor("cacheNames")
	String[] value() default {};

	@AliasFor("value")
	String[] cacheNames() default {};

	String key() default "";

	String keyGenerator() default "";

	String cacheManager() default "";

	String cacheResolver() default "";

	String condition() default "";

	String unless() default "";

}
  • 类似于 @Cacheable,该注解标识对应方法开启缓存插入操作,区别在于此操作不会去判断缓存是否存在,即只基于 condition & unless 决定是否缓存
  • 其属性基本都了解过了,它并不提供 sync 操作,即不支持同步操作

@CacheEvict

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
// 该注解表示类上所有或指定方法会对目标缓存执行剔除操作
public @interface CacheEvict {

	@AliasFor("cacheNames")
	String[] value() default {};

	@AliasFor("value")
	String[] cacheNames() default {};
	
	String key() default "";

	String keyGenerator() default "";

	String cacheManager() default "";

	String cacheResolver() default "";

	String condition() default "";

	/**
	 * 是否移除目标 Cache 的所有缓存,默认 false 意味着只清除指定 key
	 * 		的缓存,为 true 时就不允许指定 key 属性了
	 */
	boolean allEntries() default false;

	/**
	 * 剔除缓存操作是否发生在方法执行前
	 * 默认 false 表示只有目标方法 成功 执行才会进行剔除操作
	 * true 则表示先剔除,不管方法执行结果如何
	 */
	boolean beforeInvocation() default false;

}
  • 该注解开启目标方法的缓存剔除操作
  • 基于之前了解的属性拓展了:
    • allEntries:标识是否清空目标缓存,默认 false 只移除指定缓存,该属性为 true 时就不允许指定 key 属性了
    • beforeInvocation:标识是否在目标方法执行前进行剔除操作,默认 false 即目标方法执行成功后才进行移除,否则在目标方法执行前移除(无视方法是否执行成功)

@Caching

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
// 这个注解主要是针对一个方法上支持一组相(不)同缓存操作的场景
public @interface Caching {

	Cacheable[] cacheable() default {};

	CachePut[] put() default {};

	CacheEvict[] evict() default {};

}

该注解用于标识一系列缓存行为

@CacheConfig

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 在类级别用于提供默认缓存配置
public @interface CacheConfig {

	String[] cacheNames() default {};

	String keyGenerator() default "";

	String cacheManager() default "";

	String cacheResolver() default "";

}
  • 该注解用于类上,为其下所有的缓存操作提供一份默认配置
  • 主要提供属性 cacheNames keyGenerator cacheManager cacheResolver

KeyGenerator

@FunctionalInterface
public interface KeyGenerator {

	// 基于 target method params 生成 key
	Object generate(Object target, Method method, Object... params);

}
  • 上述注解中指定的 keyGenerator 即对应 KeyGenerator 对应实例的 beanName
  • 它基于 target method params 为目标缓存操作生成指定的 key
  • Spring Cache 提供的内置实现 SimpleKeyGenerator,基于参数生成对应的 SimpleKey

CacheResolver

@FunctionalInterface
public interface CacheResolver {

	// 基于 CacheOperationInvocationContext 获取对应的 Cache 集合
	Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);

}

用于解析目标缓存操作对应的 Cache 集合

AbstractCacheResolver

public abstract class AbstractCacheResolver implements CacheResolver, InitializingBean {

	@Nullable
	private CacheManager cacheManager;

	// ...

	@Override
	public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {

		// 基于 CacheOperationInvocationContext 获取 cacheNames
		Collection<String> cacheNames = getCacheNames(context);
		if (cacheNames == null) {
			return Collections.emptyList();
		}

		// 基于 cacheNames 从 CacheManager 获取对应的 Cache 集合
		Collection<Cache> result = new ArrayList<>(cacheNames.size());
		for (String cacheName : cacheNames) {
			Cache cache = getCacheManager().getCache(cacheName);
			result.add(cache);
		}
		return result;
	}

	// 子类实现,基于 CacheOperationInvocationContext 获取对应的 cacheNames
	@Nullable
	protected abstract Collection<String> getCacheNames(CacheOperationInvocationContext<?> context);

}

CacheResolver 的抽象实现:

  • 需要指定一个 CacheManager
  • getCacheNames 基于 CacheOperationInvocationContext 获取对应的 cacheNames
  • 基于上述 cacheNames,由 CacheManager 获取对应的 Cache 集合

SimpleCacheResolver

public class SimpleCacheResolver extends AbstractCacheResolver {

	// ...

	// 从 CacheOperation 中获取
	@Override
	protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
		return context.getOperation().getCacheNames();
	}

	// ...

}
  • Spring Cache 提供的内置实现,其中 getCacheNames 方法从对应的 CacheOperation 中获取 cacheNames
  • CacheOperationInvocationContext 即整个缓存操作方法执行的上下文信息,在后续的文章会具体了解

总结

本章节的内容都是定义性的注解及辅助的属性类,因此没有给出具体的示例 demo,但这些类穿插在后续的 Spring Cache 细节中

上一篇:【Spring Cache】一 Cache CacheManager

下一篇:【Spring Cache】三 CacheOperationInvocationContext CacheOperationExpressionEvaluator

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值