SpEL表达式解析注解,spring的切面,并且在扩展类实现获取到注解里面的值,并且将值保存到数据库里面

2022-12-01 13:07:58 浏览数 (1)

目录

  • 1 背景
  • 2 流程:
  • 3 举例
    • 3.1 自定义的注解
    • 3.2 创建的类
    • 3.3 创建的扩展类

1 背景

当我们想要在执行完成一个方法的时候,想要将这个方法相关的日志保存到数据库里面,比如这个方法的入参,这个方法的返回的主键的值,那么这个需要使用到spring里面的aop了。也就是功能的扩展,对一个方法功能的扩展。

2 流程:

自定义一个注解,将这个注解放到方法上面,之后利用aop重写一个类,实现功能的扩展,在这个功能的扩展类里面,从注解里面获取到对应的值,注解是放在方法上,这个注解要获取方法参数里面的值,所以要用于SpEL表达式解析.

在扩展类里面,要从注解里面获取到对应的值,之后将值保存到想要保存的数据库里面。

3 举例

3.1 自定义的注解

代码语言:javascript复制
``
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public  @interface Operator {

    public  String student() default "";
    public  String school() default "";
}

3.2 创建的类

代码语言:javascript复制
@RestController
@RequestMapping("/my")
public class textmy {

    @RequestMapping("/text")
    @Operator(student="#student",school = "school")
    public  String index(String student,String school){
//        System.out.println(student);
        return student;
    }
}

3.3 创建的扩展类

代码语言:javascript复制
@Aspect
@Component
public class MyAspect {
    /**
     * 用于SpEL表达式解析.
     */
    private static SpelExpressionParser parser = new SpelExpressionParser();

    /**
     * 用于获取方法参数定义名字.
     */
    private static DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();




    @Pointcut(" (execution(* com.controller.*.*(..)))")
    public void excudeService() {
    }
//  returning 属性,值代表返回的具体信息,都保存在这个里面
    @AfterReturning(returning="rvt",pointcut = "excudeService()")
    public void doAfter(JoinPoint joinPoint,Object rvt) {
//  参数  joinPoint   里面存放的是当前接口的  具体 信息
//  rvt  代表这个接口返回的数据


//  方法的具体信息
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//        获取到要扩展的原来的方法
        Method method = methodSignature.getMethod();
        System.out.println("方法:" method.getName());
        try {
//            getAnnotation()方法示例【通过反射获取到方法对象再获取方法对象上的注解信息】

这个是获取到一个方法上面  Operator  注解里面的全部的信息
            Operator oper = method.getAnnotation(Operator.class);
            if (oper != null) {
//                获取到方法上面注解里面的属性的值
                String student = oper.student();
                String school = oper.school();

                //将方法参数设置到上下文中
//                也就是返回了  对应关系
                EvaluationContext context = getContext(joinPoint);
//                根据对应关系  和  获取到的注解的形参 ,得到对应的方法参数的值
                String s = generateKeyBySpEL(student, context);
                String s1 = generateKeyBySpEL(school, context);

//                System.out.println("已经进入切面");
                System.out.println("这个是获取到的注解里面的值:" s s1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("记录办理过程出现异常");
        }
    }




//    JoinPoint是原来方法的全部的信息
    private EvaluationContext getContext(JoinPoint joinPoint) {
        // 通过joinPoint获取被注解方法
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
       //  以下是获取到方法所有的信息,都在method里面了
        Method method = methodSignature.getMethod();
        // 使用spring的DefaultParameterNameDiscoverer获取方法形参名数组
//        也就是将原来方法  里面的形参获得,   也就是形参现在变为数组
        String[] paramNames = nameDiscoverer.getParameterNames(method);

        // 创建  spring的表达式上下文对象
        EvaluationContext context = new StandardEvaluationContext();
       
        //获取传入目标方法的参数  也就是传入的值的集合
        Object[] args = joinPoint.getArgs();
        // 给上下文赋值,个数通过注解里面的形参进行定
        for (int i = 0; i < args.length; i  ) {
//            将方法形参  和  注解形参的  对应关系  放到上下文对象里面
            context.setVariable(paramNames[i], args[i]);
        }
//将上下文对象   ,也就是对应关系  返回
        return context;
    }






//    上下文处理器,意思是context里面已经有  注解参数和方法参数的对应关系
    private String generateKeyBySpEL(String spELString, EvaluationContext context) {
        if(StringUtils.isEmpty(spELString)){
            return "";
        }
    
        // 解析过后的Spring表达式对象
//        获取到spel的对象,也就是一个表达式的对象
        Expression expression = parser.parseExpression(spELString);
//        根据对象,从上下文对象里面获取值
        return expression.getValue(context).toString();
    }
}

0 人点赞