博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Springboot2.x AOP 实现 @Cacheable自定义TTL和自动刷新 防止缓存雪崩
阅读量:4109 次
发布时间:2019-05-25

本文共 4333 字,大约阅读时间需要 14 分钟。

Springboot2.x AOP 实现 @Cacheable自定义TTL和自动刷新

CacheManager个性化设置

  • 可以根据需要,让某些key,默认TTL与基础设置不同,直接看代码
    这不是重点,只是可以提前DIY一些东西
@Bean    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 配置序列化 // 统一默认配置,TTL为60秒 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(60)); // 针对不同key可以个性化设置 Set
cacheNames = new HashSet<>(); cacheNames.add("account"); cacheNames.add("post"); // 对每个缓存空间应用不同的配置 Map
configMap = new HashMap<>(); configMap.put("account", config.entryTtl(Duration.ofSeconds(30))); configMap.put("post", config); return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(config) .initialCacheNames(cacheNames) .withInitialCacheConfigurations(configMap) .build(); }

自定义每个缓存的TTL和自动刷新

上面的设置虽然可以提前设定每个cacheName的ttl,但是不够细,虽然Cacheable的sync可以防止缓存击穿,但是无法防止缓存雪崩。

我们可以使用AOP来完成自动刷新和自定义TTL。
代码写的比较糙,只是个例子,可以自己修改。

自己写TTL注解

import org.springframework.core.annotation.AliasFor;import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Inheritedpublic @interface CacheTTL {
@AliasFor("ttl") long value() default 60; @AliasFor("value") long ttl() default 60; long preExpireRefresh() default 10;}

AOP实现

import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.cache.annotation.Cacheable;import org.springframework.cache.interceptor.SimpleKeyGenerator;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.core.annotation.Order;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import java.lang.reflect.Method;import java.util.Arrays;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;//这里必须要比Cacheable的Aspect优先级要高@Order(value=1)@Aspect@Componentpublic class CustomCacheAspect {
private final RedisTemplate
redisTemplate; private final SimpleKeyGenerator keyGenerator = new SimpleKeyGenerator(); private final AtomicInteger asyncLock = new AtomicInteger(0); public CustomCacheAspect(RedisTemplate
redisTemplate) {
this.redisTemplate = redisTemplate; } @After(value="execution(* *..*.*(..))") public void after(JoinPoint point) {
Object target = point.getTarget(); MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); try {
if (method.isAnnotationPresent(CacheTTL.class) && method.isAnnotationPresent(Cacheable.class)) {
CacheTTL ttlData = AnnotationUtils.getAnnotation(method, CacheTTL.class); Cacheable cacheAbleData = AnnotationUtils.getAnnotation(method, Cacheable.class); long ttl = ttlData.ttl(); long preExpireRefresh = ttlData.preExpireRefresh(); String[] cacheNames = cacheAbleData.cacheNames(); //默认的keyGenerator生成,如果自定义了自己改一下 Object key = keyGenerator.generate(target, method, point.getArgs()); updateExpire(cacheNames,key,preExpireRefresh,ttl); } } catch (Exception e) {
e.printStackTrace(); } } public void updateExpire(String[] cacheNames,Object key,long preExpireRefresh,long ttl){
if (asyncLock.compareAndSet(0,1)){
Arrays.stream(cacheNames).parallel().forEach(cacheName->{
cacheName = cacheName + "::" + key; long expire = redisTemplate.getExpire(cacheName,TimeUnit.SECONDS); if (expire>0 && expire<=preExpireRefresh || expire > ttl || expire == -1){
redisTemplate.expire(cacheName, ttl, TimeUnit.SECONDS); } }); asyncLock.set(0); } }}

使用

@Cacheable(cacheNames = "account",key="#id",sync = true)    @CacheTTL(ttl = 60,preExpireRefresh = 10)    public Account findAccountByID(int id) {
return accountDao.findAccountByID(id); }

转载地址:http://yxlsi.baihongyu.com/

你可能感兴趣的文章
leetcode----179. Largest Number
查看>>
leetcode----187. Repeated DNA Sequences
查看>>
leetcode----199. Binary Tree Right Side View
查看>>
leetcode----200. Number of Islands
查看>>
leetcode----201. Bitwise AND of Numbers Range
查看>>
leetcode----207. Course Schedule
查看>>
leetcode----208. Implement Trie (Prefix Tree)
查看>>
leetcode----209. Minimum Size Subarray Sum
查看>>
leetcode----211. Add and Search Word - Data structure design
查看>>
leetcode----215. Kth Largest Element in an Array
查看>>
leetcode----216. Combination Sum III
查看>>
leetcode----220. Contains Duplicate III
查看>>
leetcode----221. Maximal Square
查看>>
leetcode----222. Count Complete Tree Nodes
查看>>
leetcode----223. Rectangle Area
查看>>
leetcode----227. Basic Calculator II
查看>>
leetcode----228. Summary Ranges
查看>>
leetcode----229. Majority Element II
查看>>
leetcode----72. Edit Distance
查看>>
Scala之flatMap操作
查看>>