springAOP+redis实现缓存

思路

在这里插入图片描述

环境准备

maven依赖

        <!--springData操作redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--springboot实现切面编程-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

把redis搭建好后,使用springboot配置连接redis参数

spring:
  redis:
    host: 192.168.17.149      #ip地址
    port: 6379              #端口号
    database: 2           #操作的库

准备自定义注解

将需要添加缓存的方法上加入注解@AddCache
将需要删除缓存的方法上加入注解@DelCache

@Target(ElementType.METHOD)//使用在方法上
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface AddCache {
    
    
}
@Target(ElementType.METHOD)//使用在方法上
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface DelCache {
    
    
}

实现添加缓存、删除缓存

String类型
Key=(包名+类名+方法名+实参)String,Value=(数据)String

@Aspect
@Configuration
public class CacheAspect {
    
    

    //注入RedisTemplate
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //添加缓存
    @Around("@annotation(com.baizhi.annotation.AddCache)")//环绕通知+切注解
    public  Object addRedisCache(ProceedingJoinPoint proceedingJoinPoint){
    
    
        System.out.println("==环绕通知  加入缓存==");

        //解决乱码问题
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        //用于拼接(包名+类名+方法名+实参)
        StringBuilder sb = new StringBuilder();//可变长字符串
        //获取类的全限定名
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        sb.append(className);
        //获取方法名
        String methodName = proceedingJoinPoint.getSignature().getName();
        sb.append(methodName);
        //获取参数(实参)
        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg: args){
    
    
            sb.append("."+arg);
        }

        //获取key(包名+类名+方法名+实参)
        String key = sb.toString();

        ValueOperations string = redisTemplate.opsForValue();

        //☆根据key去redis中判断有无数据,有:true  无:false
        Boolean aBoolean = redisTemplate.hasKey(key);
        Object result=null;
        if (aBoolean){
    
    
            //1、有数据  取出数据,返回结果
            result = string.get(key);
        }else {
    
    
            //2、没有数据  查询数据库获取结果,加入缓存,返回结果
            //①放行方法   查询数据库取出结果
            try {
    
    
                result = proceedingJoinPoint.proceed();
            } catch (Throwable throwable) {
    
    
                throwable.printStackTrace();
            }
            //②获取的返回结果加入缓存
            string.set(key,result);
        }
        return result;
    }

    //清除缓存
    @After("@annotation(com.baizhi.annotation.DelCache)")//后置通知+切注解
    public void delCache(JoinPoint joinPoint){
    
    
        System.out.println("==后置通知  清除缓存==");

        //获取类的全限定名(包名+类名)
        String className = joinPoint.getTarget().getClass().getName();
        //获取所有的key
        Set<String> keys = stringRedisTemplate.keys("*");

        for (String key : keys) {
    
    
            //判断当前key是否是以className开头的
            if (key.startsWith(className)){
    
    
                //有:删除key
                stringRedisTemplate.delete(key);
            }
        }
    }
}

优化添加缓存、删除缓存

Hash类型
Key=(类的全限定名)String,Value=( key=(方法名+实参)String,value=(数据)String )

@Aspect
@Configuration
public class CacheAspectHash {
    
    

    //注入RedisTemplate
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    //添加缓存
    @Around("@annotation(com.baizhi.annotation.AddCache)")//环绕通知+切注解
    public  Object addRedisCache(ProceedingJoinPoint proceedingJoinPoint){
    
    
        System.out.println("==环绕通知  加入缓存==");
        /*
         * 解决序列化乱码
         * */
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);


        //Key=类的全限定名,Value=( key=方法名+实参,value=数据 )


        //获取类的全向定名  com/baizhi/impl/feedbackServiceImpl
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        StringBuilder sb = new StringBuilder();

        //获取方法名
        String methodName = proceedingJoinPoint.getSignature().getName();
        sb.append(methodName);
        //获取参数
        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg: args){
    
    
            sb.append("."+arg);
        }

        //获取小key
        String key = sb.toString();

        HashOperations hash = redisTemplate.opsForHash();

        //☆判断大key中有没有小key,有:true  无:false
        Boolean aBoolean = hash.hasKey(className, key);
        Object result=null;
        if (aBoolean){
    
    
            //1、有数据  取出数据,返回结果
            result = hash.get(className,key);
        }else {
    
    
            //2、没有数据  查询数据库获取结果,加入缓存,返回结果
            //①放行方法   查询数据库取出结果
            try {
    
    
                result = proceedingJoinPoint.proceed();
            } catch (Throwable throwable) {
    
    
                throwable.printStackTrace();
            }
            //②获取的返回结果加入缓存
            hash.put(className,key,result);
        }
        return result;
    }

    //清除缓存
    @After("@annotation(com.baizhi.annotation.DelCache)")//后置通知+切注解
    public void delXCache(JoinPoint joinPoint){
    
    
        System.out.println("==后置通知  清除缓存==");

        //Key=类的全限定名,Value=( key=方法名+实参,value=数据 )

        //获取类的全限定名
        String className = joinPoint.getTarget().getClass().getName();
        Boolean bBoolean = stringRedisTemplate.delete(className);
        System.out.println("删除缓存"+bBoolean);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45928727/article/details/107326619