缓存对开发者来说肯定不陌生,很多时候为了控制大量用户访问对数据库产生压力,我们都会在中加一层缓存。将数据库的数据暂时缓存在缓存中,减轻数据库的压力。今天给大家介绍一种添加缓存的方式,一次编写永久使用。
我将用“注解+切面”的方式实现添加缓存。下面是我的实现:
概述
1、定义注解(指定使用范围用于方法上)
2、定义切面切刚才的注解
3、在我们要添加缓存的方法上加上注解
4、只要调用这方法就会自动加上缓存
具体实现详细介绍
步骤1:自定义一个注解
此注解接受两个参数,一个是缓存前缀,另一个是缓存时间,并且该注解只能用于在方法上添加。
package com.omiga.aop;
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 RedisAopAnnotation {
/**
* 缓存前缀
*
* @return 缓存前缀
*/
String keyPrefix() default "";
/**
* 缓存失效时间
*
* @return 缓存失效时间
*/
int expireTime() default 10;
}
步骤2:添加一个切面
添加切面,切我们刚才定义的注解。我将以“注解中设置的缓存前缀+(方法名+参数值)加密后的字符”作为缓存key,并且使用注解中设置的缓存时间为具体的缓存时间。先从缓存中读取数据,如果读到数据就直接返回,没有读到再到数据库中查询并且写到缓存中。
package com.omiga.aop;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@Component
@Aspect
public class RedisAop {
@Around(value="@annotation(com.omiga.aop.RedisAopAnnotation)")
public Object around(ProceedingJoinPoint joinPoint){
Object object = null;
try {
Class<?> clazz = joinPoint.getTarget().getClass();
Signature signature = joinPoint.getSignature();
String name = signature.getName();
//先获取目标方法参数
StringBuffer keyBuffer = new StringBuffer(name);
Object[] args = joinPoint.getArgs();
Object valueObject;
//遍历参数的值,然后组装成redis的key
if (args != null && args.length > 0) {
for (Object arg : args) {
Class<? extends Object> argClazz = arg.getClass();
Field[] fields = argClazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
valueObject = field.get(arg);
if (null != valueObject) {
keyBuffer.append(field.get(arg).toString());
}
}
}
}
String key = Hashing.sha256().newHasher().putString(keyBuffer.toString(), Charsets.UTF_8).hash().toString();
MethodSignature methodSignature = (MethodSignature) signature;
Method declaredMethod = clazz.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
RedisAopAnnotation annotation = declaredMethod.getAnnotation(RedisAopAnnotation.class);
int expireTime = annotation.expireTime();
String keyPrefix = annotation.keyPrefix();
String redisKey = keyPrefix + key;
//从缓存中读取数据
//redis.get(redisKey);
Object objectFromRedis = null;
if (null != objectFromRedis) {
return objectFromRedis;
}
object = joinPoint.proceed();
if (object != null) {
//写入缓存
//redis.set(redisKey,object,expireTime);
}
}catch (Exception e){
System.out.println(e);
} catch (Throwable e) {
System.out.println(e);
}
return object;
}
}
步骤3:添加一个测试方法
在测试方法中,添加上我们自定义的注解,这样这个方法就添加上缓存了
package com.omiga.aop;
import org.springframework.stereotype.Component;
@Component
public class RedisAopManager {
@RedisAopAnnotation
public String doAnyThing(String name){
return name;
}
}
步骤4:单元测试调用
运行testAop 即可
package com.omiga.test;
import com.omiga.aop.RedisAop;
import com.omiga.aop.RedisAopManager;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest(classes = AopTest.Config.class)
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
public class AopTest {
@Autowired
private RedisAopManager redisAopManager;
@Test
public void testAop(){
redisAopManager.doAnyThing("omiga");
}
@Configuration
@Import({})
public static class Config{
@Bean
public RedisAopManager redisAopManager(){
return new RedisAopManager();
}
@Bean
public RedisAop redisAop(){
return new RedisAop();
}
}
}
上面就是整个代码,大家拷贝下来就能运行。需要的pom依赖:
<!--切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
<!--guava-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
网友评论