欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 打造分布式缓存组件【场景】

打造分布式缓存组件【场景】

2025/2/24 0:38:54 来源:https://blog.csdn.net/weixin_38425605/article/details/141002401  浏览:    关键词:打造分布式缓存组件【场景】

本文将采用AOP + 反射 + Redis自定义缓存标签,重构缓存代码,打造基础架构分布式缓存组件

配置

需要在Redis配置类中开启AOP自动代理,即通过==@EnableAspectJAutoProxy ==注解实现该功能

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;import java.lang.reflect.Method;
import java.time.Duration;/*** Redis配置类**/
@Configuration
@EnableCaching
@EnableAspectJAutoProxy // 开启AOP自动代理
public class RedisConfig {@Bean@Primarypublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);//String的序列化方式StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// 使用GenericJackson2JsonRedisSerializer 替换默认序列化(默认采用的是JDK序列化)GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();//序列号key valueredisTemplate.setKeySerializer(stringRedisSerializer);redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);redisTemplate.setHashKeySerializer(stringRedisSerializer);redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}
}

自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BaizeRedisCache {// redis的key前缀String keyPrefix();// SpringEL表达式,解析占位符对应的匹配value值String matchValue();}

定义Redis缓存组件切面类

import jakarta.annotation.Resource;
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.core.DefaultParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** @Description:redis缓存组件切面类* @Author: smart* @Date: 2024/8/7 8:40*/
@Aspect
@Component
public class BaizeRedisCacheAspect {@Resourceprivate RedisTemplate redisTemplate;// 配置织入点@Pointcut("@annotation(com.atguigu.daijia.common.config.redis.BaizeRedisCache)")public void cachePoint(){}@Around("cachePoint()")public Object doCache(ProceedingJoinPoint joinPoint){// TODOObject result = null;try{// 1、获取重载后的方法名MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();// 2、确定方法名上配置的注解标签BaizeRedisCache baizeRedisCache = method.getAnnotation(BaizeRedisCache.class);// 3、获得该注解标签上配置的参数进行封装和调用String keyPrefix = baizeRedisCache.keyPrefix();String matchValueSpringEL = baizeRedisCache.matchValue();// 4、SpringEL解析器SpelExpressionParser parser = new SpelExpressionParser();Expression expression = parser.parseExpression(matchValueSpringEL);StandardEvaluationContext context = new StandardEvaluationContext();// 5、获得方法里的形参个数Object[] args = joinPoint.getArgs();DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();String[] parameterNames = discoverer.getParameterNames(method);for (int i = 0; i < parameterNames.length; i++) {System.out.println("获得方法里参数名和值: " + parameterNames[i] + "\t" + args[i].toString());context.setVariable(parameterNames[i], args[i].toString());}// 6、拼接redis最终key形式String key = keyPrefix + ":" + expression.getValue(context).toString();System.out.println("拼接redis的最终key形式: " + key);// 7、先去redis中查询是否存在数据result = redisTemplate.opsForValue().get(key);if (result != null){// 若redis存在则直接返回结果,无需到数据库中查询return result;}// 8、redis中没有则去数据库中查询result = joinPoint.proceed();// 9、主业务逻辑查询完之后,将数据存入redisif (result != null){redisTemplate.opsForValue().set(key, result);}}catch (Throwable throwable){throwable.printStackTrace();}return result;}
}

应用

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词