本文共 3095 字,大约阅读时间需要 10 分钟。
spring cache定义的接口
如下图,涉及到的操作有get、put、evict,对应于查询、更新、清除缓存对应的注解为cacheable、cacheevict、cacheput操作,可以查看源码分析注解的字段了解注解的用法参考:SpEL上下文数据
spring cache支持SpEL表达式methodName
root对象
当前被调用的方法名
method
root对象
当前被调用的方法
target
root对象
当前被调用的目标对象
targetClass
root对象
当前被调用的目标对象类
args
root对象
当前被调用的方法的参数列表
caches
root对象
当前方法调用使用的缓存列表(如@Cacheable(value={"cache1", "cache2"})),则有两个cache
argument name
执行上下文
当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数
result
执行上下文
方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,'cache evict'的beforeInvocation=false)
通过这些数据我们可能实现比较复杂的缓存逻辑了,后边再来介绍。
execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments());
根据 类 + 方法 ,获取定义的缓存操作,构建缓存上下文
缓存的执行流程
1、首先执行@CacheEvict(如果beforeInvocation=true且condition 通过),如果allEntries=true,则清空所有 2、接着收集@Cacheable(如果condition 通过,且key对应的数据不在缓存),放入cachePutRequests(也就是说如果cachePutRequests为空,则数据在缓存中) 3、如果cachePutRequests为空且没有@CachePut操作,那么将查找@Cacheable的缓存,否则result=缓存数据(也就是说只要当没有cache put请求时才会查找缓存) 4、如果没有找到缓存,那么调用实际的API,把结果放入result 5、如果有@CachePut操作(如果condition 通过),那么放入cachePutRequests 6、执行cachePutRequests,将数据写入缓存(unless为空或者unless解析结果为false); 7、执行@CacheEvict(如果beforeInvocation=false 且 condition 通过),如果allEntries=true,则清空所有// Process any early evictions processCacheEvicts(contexts.get(CacheEvictOperation.class), true, CacheOperationExpressionEvaluator.NO_RESULT); // Check if we have a cached item matching the conditions Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class)); // Collect puts from any @Cacheable miss, if no cached item is found ListcachePutRequests = new LinkedList (); if (cacheHit == null) { collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests); } Object cacheValue; Object returnValue; if (cacheHit != null && cachePutRequests.isEmpty() && !hasCachePut(contexts)) { // If there are no put requests, just use the cache hit cacheValue = cacheHit.get(); returnValue = wrapCacheValue(method, cacheValue); } else { // Invoke the method if we don't have a cache hit returnValue = invokeOperation(invoker); cacheValue = unwrapReturnValue(returnValue); } // Collect any explicit @CachePuts collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests); // Process any collected put requests, either from @CachePut or a @Cacheable miss for (CachePutRequest cachePutRequest : cachePutRequests) { cachePutRequest.apply(cacheValue); } // Process any late evictions processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
如何定义自己的缓存管理器CacheManager
spring cache的CacheManager的体系结构如下默认提供了Ehcache和JCache的支持,并且缓存还支持事务(事务回退缓存回退),如果自定义缓存可以选择继承其中的某一个,只需要实现其中一个抽象方法,将实现了cache接口的缓存注入到缓存管理器即可转载地址:http://bczsl.baihongyu.com/