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",结果如下

  • 相关阅读:
    【LeetCode】119. Pascal's Triangle II
    随机梯度下降(Stochastic gradient descent)和 批量梯度下降(Batch gradient descent )的公式对比、实现对比[转]
    linux下一些可用库
    malloc分配的内存空间是连续的吗
    语言模型训练网站
    relocation 错误
    undefined reference to `dlopen'
    静态库之间有依赖关系顺序很重要
    C++引用详解
    malloc原理和内存碎片[转]
  • 原文地址:https://www.cnblogs.com/hhhshct/p/10636159.html
Copyright © 2011-2022 走看看