AOP实现redis缓存

AOP实现redis缓存

redis使用AOP实现记录缓存, 可以大大减少代码量, 提高工作效率

1. 配置redis

1.1配置文件

创建一个redis.properties

# 配置单台redis
redis.host=192.168.126.129
redis.port=6379

1.2编辑配置类

@Configuration  //标识我是配置类
@PropertySource("classpath:/properties/redis.properties") // 读取配置文件
public class RedisConfig {

    @Value("${redis.host}")
    private String  host;
    @Value("${redis.port}")
    private Integer port;

    @Bean
    public Jedis jedis(){
        //数据写死?????????
        return new Jedis(host,port);
    }
}

2. 自定义注解

在指定的方法上使用, 把方法执行的结果使用AOP自动解析为json并存入redis 缓存

@Target(ElementType.METHOD)         //注解在方法中使用
@Retention(RetentionPolicy.RUNTIME) //运行期有效
public @interface CacheFind {

    String key();              //1.设定key 用户自己设定
    int seconds() default  0;  //2.可以指定超时时间,也可以不指定.

}

3. AOP实现redis缓存

@Component  //1.我是一个javaBean
@Aspect     //2.我是一个切面
public class CacheAOP {

    //引入redis缓存配置
    @Autowired
    private Jedis jedis;


    /**
     * AOP缓存实现的业务策略
     * 1.切入点表达式应该拦截  @CacheFind注解
     * 2.通知方法: 环绕通知
     * 注意事项:  如果使用环绕通知,则必须在第一个参数的位置添加 ProceedingJoinPoint
     *
     * 动态获取注解参数的步骤:
     *  1.@annotation(cacheFind)   切入点表达式要求拦截一个类型为cacheFind注解.
     *  2.并且利用连接点为参数中的cacheFind赋值.
     * */

    @Around("@annotation(cacheFind)")
    public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind){
        try {
            // 目标方法执行的返回结果
            Object result = null;
            //1.如何动态获取注解中的数据
            String prekey = cacheFind.key();
            //2.动态获取方法中的参数  将数组转化为字符串
            String args = Arrays.toString(joinPoint.getArgs());
            String key = prekey + "::" + args;
            //3.检验redis中是否有数据
            if(jedis.exists(key)){
                //有缓存  从redis缓存中获取json 之后还原对象返回
                String json = jedis.get(key);
                //target代表这目标方法的返回值类型......
                //动态获取目标方法的返回值类型??   向上造型 不用强转   向下造型
                MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
               Class returnClass = methodSignature.getReturnType();
                //将json数据转化为对象
                result = ObjectMapperUtil.toObject(json, returnClass);
                System.out.println("AOP实现缓存查询!!!!");

            }else{
                //第一次查询数据库.
                result = joinPoint.proceed();    //执行目标方法.
                System.out.println("AOP执行数据库操作");
                //2.将数据保存到redis中
                String json = ObjectMapperUtil.toJSON(result);
                if(cacheFind.seconds()>0) //表示需要设定超时时间
                    jedis.setex(key, cacheFind.seconds(), json);
                else
                    //不需要超时
                    jedis.set(key, json);
            }
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            throw new RuntimeException(throwable);  //将检查异常,转化为运行时异常
        }
    }
}

4. 测试

假设下面为service层的方法

@CacheFind(key = "FIND_NAME")
public String findName() {
    return "hello world";
}

在controller中调用, 多次请求此controller的结果

AOP执行数据库操作
AOP实现缓存查询!!!!
AOP实现缓存查询!!!!
AOP实现缓存查询!!!!
......
posted @ 2020-08-16 11:09  zpk-aaron  阅读(1309)  评论(0编辑  收藏  举报