Redis统一注解让缓存变得更有效(redis统一注解)
Redis统一注解——让缓存变得更有效
缓存是提高应用性能和可用性的有效方式,而Redis作为一个高性能的NoSQL数据库和缓存产品,被越来越多的应用程序所采用。但是,缓存使用不当也可能带来一些问题,比如缓存的更新和失效,缓存穿透等。因此,有必要对缓存进行有效的管理和维护。
在Java开发中,我们可以使用注解的方式来统一管理Redis缓存,让代码更加简洁、易懂。下面我们就来看看如何在Java中使用Redis注解。
需要引入jedis和spring-data-redis依赖,在pom.xml中添加如下代码:
redis.clientsjedis
3.6.0
org.springframework.bootspring-boot-starter-data-redis
接下来,需要配置Redis连接池和RedisTemplate,这里代码如下:
@Configuration
public class RedisConfig {
@Beanpublic JedisPool jedisPool() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();//配置Jedis参数
JedisPool jedisPool = new JedisPool(jedisPoolConfig, "localhost", 6379, 10000, null);return jedisPool;
}
@Beanpublic RedisTemplate redisTemplate(JedisConnectionFactory connectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(connectionFactory);//设置默认的Serialize,包含 keySerializer & valueSerializer
redisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer(Object.class));redisTemplate.afterPropertiesSet();
return redisTemplate;}
@Beanpublic JedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();configuration.setHostName("localhost");
configuration.setPort(6379);configuration.setDatabase(0);
JedisConnectionFactory factory = new JedisConnectionFactory(configuration);factory.afterPropertiesSet();
return factory;}
}
接下来,我们就可以开始使用注解了。首先定义一个缓存注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)public @interface RedisCache {
String key();
Class returnType() default String.class;
int expire() default 3600;
}
该注解有三个属性:
– key:缓存key的生成规则,可通过SpEL表达式来计算
– returnType:缓存返回值类型
– expire:缓存过期时间,单位为秒
接下来,我们定义一个切面RedisCacheAspect,用于拦截被@RedisCache注解的方法,并处理缓存的读写逻辑:
@Aspect
@Componentpublic class RedisCacheAspect {
@Autowiredprivate RedisTemplate redisTemplate;
@Autowiredprivate JedisPool jedisPool;
@Pointcut(value = "@annotation(com.example.redisdemo.cache.RedisCache)")public void redisCachePointcut() {
}
@Around("redisCachePointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//获取RedisCache注解MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();RedisCache annotation = AnnotationUtils.findAnnotation(method, RedisCache.class);
//构造缓存keyString[] parameterNames = signature.getParameterNames();
Object[] args = joinPoint.getArgs();ExpressionParser expressionParser = new SpelExpressionParser();
String keyExpression = annotation.key();StandardEvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i context.setVariable(parameterNames[i], args[i]);
}String key = expressionParser.parseExpression(keyExpression).getValue(context, String.class);
//读取缓存String redisKey = "redis:" + key;
if (redisTemplate.hasKey(redisKey)) {return redisTemplate.opsForValue().get(redisKey);
}Jedis jedis = jedisPool.getResource();
try {if (jedis.exists(redisKey)) {
Object value = redisTemplate.getDefaultSerializer().deserialize(jedis.get(redisKey.getBytes()));redisTemplate.opsForValue().set(redisKey, value, annotation.expire(), TimeUnit.SECONDS);
return value;}
//调用目标方法Object result = joinPoint.proceed();
if (result != null) {redisTemplate.opsForValue().set(redisKey, result, annotation.expire(), TimeUnit.SECONDS);
//返回结果return result;
}} finally {
jedis.close();}
return null;}
}
该切面主要包括以下几个步骤:
– 获取目标方法上的@RedisCache注解
– 构造缓存key,使用SpEL表达式计算缓存的变量值
– 读取缓存,先从Redis缓存中读取数据,如果不存在就从Jedis中读取
– 调用目标方法,如果返回值不为null,就将其写入到Redis缓存中
在需要使用Redis缓存的方法上添加@RedisCache注解即可:
@RedisCache(key = "'user:' + #userId")
public User getUserById(String userId) {//查询数据库获取User对象
User user = userRepository.findById(userId);return user;
}
这样,我们就实现了一种简单而有效的Redis缓存管理方式。通过使用注解,我们可以轻松地统一管理Redis缓存,在提高系统性能的同时,也能有效避免缓存失效和穿透等问题。