All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hanqunfeng.reactive.redis.cache.aop.ReactiveRedisCacheAspect Maven / Gradle / Ivy

package com.hanqunfeng.reactive.redis.cache.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 

redis缓存aop

* Created by hanqf on 2020/11/21 16:16. */ @Component //标识是一个Aspect代理类 @Aspect //如果有多个切面拦截相同的切点,可以用@Order指定执行顺序 //@Order(1) @Slf4j public class ReactiveRedisCacheAspect { @Autowired private RedisTemplate redisTemplate; @Pointcut("@annotation(com.hanqunfeng.reactive.redis.cache.aop.ReactiveRedisCacheable)") public void cacheablePointCut() { } @Pointcut("@annotation(com.hanqunfeng.reactive.redis.cache.aop.ReactiveRedisCacheEvict)") public void cacheEvictPointCut() { } @Pointcut("@annotation(com.hanqunfeng.reactive.redis.cache.aop.ReactiveRedisCachePut)") public void cachePutPointCut() { } @Pointcut("@annotation(com.hanqunfeng.reactive.redis.cache.aop.ReactiveRedisCaching)") public void cachingPointCut() { } //环绕通知,一般不建议使用,可以通过@Before和@AfterReturning实现 //但是响应式方法只能通过环绕通知实现aop,因为其它通知会导致不再同一个线程执行 @Around("cacheablePointCut()") public Object cacheableAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { log.debug("ReactiveRedisCacheAspect cacheableAround...."); MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); Method method = methodSignature.getMethod(); String returnTypeName = method.getReturnType().getSimpleName(); ReactiveRedisCacheable annotation = method.getAnnotation(ReactiveRedisCacheable.class); String cacheName = annotation.cacheName(); String key = annotation.key(); long timeout = annotation.timeout(); //转换EL表达式 cacheName = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, cacheName); key = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, key); String redis_key = redisKey(cacheName, key); boolean hasKey = redisTemplate.hasKey(redis_key); if (hasKey) { Object o = redisTemplate.opsForValue().get(redis_key); log.debug("The key[{}] exists,method body not executed", redis_key); if (returnTypeName.equals("Flux")) { return Flux.fromIterable((List) o); } else if (returnTypeName.equals("Mono")) { return Mono.just(o); } else { return o; } } else { log.debug("The key[{}] does not exist,method body executed", redis_key); //实际执行的方法 Object proceed = proceedingJoinPoint.proceed(); if (returnTypeName.equals("Flux")) { return ((Flux) proceed).collectList().doOnNext(list -> { redisTemplate.opsForValue().set(redis_key, list, timeout, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", redis_key); }).flatMapMany(list -> Flux.fromIterable((List) list)); } else if (returnTypeName.equals("Mono")) { return ((Mono) proceed).doOnNext(obj -> { redisTemplate.opsForValue().set(redis_key, obj, timeout, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", redis_key); }); } else { return proceed; } } } @Around("cacheEvictPointCut()") public Object cacheEvictAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { log.debug("ReactiveRedisCacheAspect cacheEvictAround...."); MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); Method method = methodSignature.getMethod(); String returnTypeName = method.getReturnType().getSimpleName(); ReactiveRedisCacheEvict annotation = method.getAnnotation(ReactiveRedisCacheEvict.class); String cacheName = annotation.cacheName(); String key = annotation.key(); boolean allEntries = annotation.allEntries(); boolean beforeInvocation = annotation.beforeInvocation(); //转换EL表达式 cacheName = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, cacheName); key = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, key); //执行方法前清除缓存 if (beforeInvocation) { //清除全部缓存 deleteRedisCache(cacheName, key, allEntries); //实际执行的方法 log.debug("beforeInvocation=[{}],Method body executed", beforeInvocation); Object proceed = proceedingJoinPoint.proceed(); return proceed; } else {//成功执行方法后清除缓存 //实际执行的方法 Object proceed = proceedingJoinPoint.proceed(); log.debug("beforeInvocation=[{}],Method body executed", beforeInvocation); final String cacheNameTemp = cacheName; final String keyTemp = key; if (returnTypeName.equals("Flux")) { return ((Flux) proceed).collectList().doOnNext(list -> { //清除全部缓存 deleteRedisCache(cacheNameTemp, keyTemp, allEntries); }).flatMapMany(list -> Flux.fromIterable((List) list)); } else if (returnTypeName.equals("Mono")) { return ((Mono) proceed).doOnNext(obj -> { //清除全部缓存 deleteRedisCache(cacheNameTemp, keyTemp, allEntries); }); } else { return proceed; } } } @Around("cachePutPointCut()") public Object cachePutAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { log.debug("ReactiveRedisCacheAspect cachePutAround...."); MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); Method method = methodSignature.getMethod(); String returnTypeName = method.getReturnType().getSimpleName(); ReactiveRedisCachePut annotation = method.getAnnotation(ReactiveRedisCachePut.class); String cacheName = annotation.cacheName(); String key = annotation.key(); long timeout = annotation.timeout(); //转换EL表达式 cacheName = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, cacheName); key = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, key); String redis_key = redisKey(cacheName, key); boolean hasKey = redisTemplate.hasKey(redis_key); if (hasKey) { deleteRedisCache(redis_key, false); } //实际执行的方法 Object proceed = proceedingJoinPoint.proceed(); log.debug("Method body executed"); if (returnTypeName.equals("Flux")) { return ((Flux) proceed).collectList().doOnNext(list -> { redisTemplate.opsForValue().set(redis_key, list, timeout, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", redis_key); }) .flatMapMany(list -> Flux.fromIterable((List) list)); } else if (returnTypeName.equals("Mono")) { return ((Mono) proceed).doOnNext(obj -> { redisTemplate.opsForValue().set(redis_key, obj, timeout, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", redis_key); }); } else { return proceed; } } @Around("cachingPointCut()") public Object cachingAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { log.debug("ReactiveRedisCacheAspect cachingAround...."); MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); Method method = methodSignature.getMethod(); String returnTypeName = method.getReturnType().getSimpleName(); ReactiveRedisCaching annotation = method.getAnnotation(ReactiveRedisCaching.class); ReactiveRedisCacheEvict[] cacheEvicts = annotation.evict(); ReactiveRedisCachePut[] cachePuts = annotation.put(); ReactiveRedisCacheable[] cacheables = annotation.cacheable(); //规则: //1.cacheables不能与cacheEvicts或者cachePuts同时存在,因为后者一定会执行方法主体,达不到调用缓存的目的,所以当cacheables存在时,后者即便指定也不执行 //2.先执行cacheEvicts,再执行cachePuts if (cacheables.length > 0) { Map key_map = new HashMap<>(); List key_list = new ArrayList<>(); Arrays.stream(cacheables).forEach(cacheable -> { String cacheName = cacheable.cacheName(); String key = cacheable.key(); long timeout = cacheable.timeout(); //转换EL表达式 cacheName = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, cacheName); key = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, key); String redis_key = redisKey(cacheName, key); key_map.put(redis_key, timeout); key_list.add(redis_key); }); AtomicBoolean isAllKeyHas = new AtomicBoolean(true); key_list.forEach(key -> { if (!redisTemplate.hasKey(key)) { isAllKeyHas.set(false); } }); //全部key都有值,则直接返回缓存 if (isAllKeyHas.get()) { Object o = redisTemplate.opsForValue().get(key_list.get(0)); log.debug("The key[{}] exists,method body not executed", key_list.get(0)); if (returnTypeName.equals("Flux")) { return Flux.fromIterable((List) o); } else if (returnTypeName.equals("Mono")) { return Mono.just(o); } else { return o; } } else { //实际执行的方法 Object proceed = proceedingJoinPoint.proceed(); log.debug("The key[{}] does not exist,method body executed", key_list.get(0)); if (returnTypeName.equals("Flux")) { return ((Flux) proceed).collectList() .doOnNext(list -> key_map.forEach((key, val) -> { redisTemplate.opsForValue().set(key, list, val, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", key); })) .flatMapMany(list -> Flux.fromIterable((List) list)); } else if (returnTypeName.equals("Mono")) { return ((Mono) proceed) .doOnNext(obj -> key_map.forEach((key, val) -> { redisTemplate.opsForValue().set(key, obj, val, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", key); })); } else { return proceed; } } } else { Map map = new HashMap<>(); if (cacheEvicts.length > 0) { Arrays.stream(cacheEvicts).forEach(cacheEvict -> { String cacheName = cacheEvict.cacheName(); String key = cacheEvict.key(); boolean allEntries = cacheEvict.allEntries(); boolean beforeInvocation = cacheEvict.beforeInvocation(); //转换EL表达式 cacheName = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, cacheName); key = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, key); if (beforeInvocation) { //执行方法前清除缓存 //清除全部缓存 deleteRedisCache(cacheName, key, allEntries); } else { //成功执行方法后清除缓存,先保存到map中 //清除全部缓存 if (allEntries) { map.put(cacheName, true); } else { map.put(redisKey(cacheName, key), false); } } }); } //实际执行的方法 Object proceed = proceedingJoinPoint.proceed(); log.debug("Method body executed"); if (cachePuts.length > 0) { Map key_map = new HashMap<>(); Arrays.stream(cachePuts).forEach(cachePut -> { String cacheName = cachePut.cacheName(); String key = cachePut.key(); long timeout = cachePut.timeout(); //转换EL表达式 cacheName = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, cacheName); key = (String) AspectSupportUtils.getKeyValue(proceedingJoinPoint, key); String redis_key = redisKey(cacheName, key); key_map.put(redis_key, timeout); boolean hasKey = redisTemplate.hasKey(redis_key); if (hasKey) { deleteRedisCache(redis_key, false); } }); if (returnTypeName.equals("Flux")) { return ((Flux) proceed).collectList() .doOnNext(list -> { //执行方法后清除缓存 if (map.size() > 0) { map.forEach((key, val) -> { deleteRedisCache(key, val); }); } key_map.forEach((key, val) -> { redisTemplate.opsForValue().set(key, list, val, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", key); }); }) .flatMapMany(list -> Flux.fromIterable((List) list)); } else if (returnTypeName.equals("Mono")) { return ((Mono) proceed) .doOnNext(obj -> { //执行方法后清除缓存 if (map.size() > 0) { map.forEach((key, val) -> deleteRedisCache(key, val)); } key_map.forEach((key, val) -> { redisTemplate.opsForValue().set(key, obj, val, TimeUnit.SECONDS); log.debug("The key[{}] has been cached", key); }); }); } else { return proceed; } } else { if (returnTypeName.equals("Flux")) { return ((Flux) proceed).collectList().doOnNext(list -> { //执行方法后清除缓存 if (map.size() > 0) { map.forEach((key, val) -> deleteRedisCache(key, val)); } }).flatMapMany(list -> Flux.fromIterable((List) list)); } else if (returnTypeName.equals("Mono")) { return ((Mono) proceed).doOnNext(obj -> { //执行方法后清除缓存 if (map.size() > 0) { map.forEach((key, val) -> deleteRedisCache(key, val)); } }); } else { return proceed; } } } } private void deleteRedisCache(String key, boolean clearAll) { if (clearAll) { Set keys = redisTemplate.keys(key + ":*"); if (!keys.isEmpty()) { log.debug("The key[{}:*] has been cleared", key); redisTemplate.delete(keys); } else { log.debug("The key[{}:*] does not exist", key); } } else { if (redisTemplate.hasKey(key)) { log.debug("The key[{}] has been cleared", key); redisTemplate.delete(key); } else { log.debug("The key[{}] does not exist", key); } } } private void deleteRedisCache(String cacheName, String key, boolean clearAll) { String redis_key; if (clearAll) { redis_key = cacheName; } else { redis_key = redisKey(cacheName, key); } deleteRedisCache(redis_key, clearAll); } private String redisKey(String cacheName, String key) { return cacheName + ":" + key; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy