美文网首页
切面和缓存一起使用让添加缓存更简单

切面和缓存一起使用让添加缓存更简单

作者: 逐影随行 | 来源:发表于2021-07-26 17:13 被阅读0次

    缓存对开发者来说肯定不陌生,很多时候为了控制大量用户访问对数据库产生压力,我们都会在中加一层缓存。将数据库的数据暂时缓存在缓存中,减轻数据库的压力。今天给大家介绍一种添加缓存的方式,一次编写永久使用。


    我将用“注解+切面”的方式实现添加缓存。下面是我的实现:

    概述

    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>
    

    相关文章

      网友评论

          本文标题:切面和缓存一起使用让添加缓存更简单

          本文链接:https://www.haomeiwen.com/subject/btjgmltx.html