zoukankan      html  css  js  c++  java
  • 使用spring EL表达式+自定义切面封装缓存模块

      需求是这样的,业务代码需要使用到缓存功能以减少数据库压力,使用redis来实现,并且需要生成缓存的key由方法的传参拼接而成(貌似也只能这样才能保证同样的select查询可以使用缓存),简单的方式就是在需要缓存的方法内加上大概这样的逻辑:查询缓存--->没有则查询数据库 --->查询结果以key-value形式放入缓存,这样对业务代码造成了侵入,并且产生大量重复的代码,很不优雅,所以决定自己封装一个缓存模块,在需要缓存的地方只需要加入一个注解即可。

      首先自定义一个注解

    package com.example.test.aspect;
    
    
    import java.lang.annotation.*;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Inherited
    public @interface MyCache {
    
        String value() default "";
    }

      定义切面

    package com.example.test.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.expression.EvaluationContext;
    import org.springframework.expression.Expression;
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.expression.spel.support.StandardEvaluationContext;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    
    @Component
    @Aspect
    public class MyAspect {
    
        //切入点,带有Myche注解并且是UserService类下的方法
        @Pointcut("@annotation(com.example.test.aspect.MyCache)&&execution(* com.example.test.service.UserService.*(..))")
        public  void pointCut(){};
    
        @Around("pointCut()")
        public Object cache(ProceedingJoinPoint joinPoint)throws Throwable{
            //获取方法签名
            MethodSignature  methodSignature = (MethodSignature) joinPoint.getSignature();
            //获取目标方法
            Method method = methodSignature.getMethod();
    //       Method method2 = joinPoint.getTarget().getClass().getMethod(methodSignature.getName(),methodSignature.getParameterTypes());
            //获取方法上的注解
            MyCache myCache = method.getDeclaredAnnotation(MyCache.class);
            //得到el表达式
            String el = myCache.value();
            //解析el表达式,将#id等替换为参数值
            ExpressionParser expressionParser = new SpelExpressionParser();
            Expression expression = expressionParser.parseExpression(el);
            EvaluationContext context = new StandardEvaluationContext();
            String[] parameterNames = methodSignature.getParameterNames();
            Object[] args = joinPoint.getArgs();
            for (int i = 0; i <parameterNames.length ; i++) {
                context.setVariable(parameterNames[i],args[i]);
            }
            String key = expression.getValue(context).toString();
            System.out.println(key);
            //根据key从缓存中拿数据,这里省略
            
            //如果缓存中没有则执行目标方法
            Object o =   joinPoint.proceed();
            //将结果放入缓存,这里省略
            
            return o;
            
        }
    }

      测试的service

    package com.example.test.service;
    
    import com.example.test.aspect.MyCache;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService implements UserServiceInterface{
        
    
        @MyCache("'asd_' + #id")
        @Override
        public void addUser(String id,String name){
            System.out.println(id + "----" + name);
        }
    }

      测试类,这里是springboot项目

    package com.example.test;
    
    import com.example.test.service.UserService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class TestApplicationTests {
    
        @Autowired
        private UserService userService;
    
        @Test
        public void contextLoads() {
            System.out.println(userService.getClass().getName());
    
            userService.addUser("12345" ,"zhagnsan");
        }
    
    }

      执行结果如下:

      修改UserService上的注解为:"'asd_' + #id + '_' + #name",结果如下

  • 相关阅读:
    How To Scan QRCode For UWP (4)
    How To Crop Bitmap For UWP
    How To Scan QRCode For UWP (3)
    How To Scan QRCode For UWP (2)
    How To Scan QRCode For UWP (1)
    How to change windows applicatioin's position via Win32 API
    8 Ways to Become a Better Coder
    How to resize or create a thumbnail image from file stream on UWP
    C# winform压缩文件夹带进度条
    MS ACCESS MID函数
  • 原文地址:https://www.cnblogs.com/hhhshct/p/10636159.html
Copyright © 2011-2022 走看看