前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpEL表达式解析注解,spring的切面,并且在扩展类实现获取到注解里面的值,并且将值保存到数据库里面

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

作者头像
一写代码就开心
发布2022-12-01 13:07:58
1.1K0
发布2022-12-01 13:07:58
举报
文章被收录于专栏:java和python

目录

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();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 1 背景
  • 2 流程:
  • 3 举例
    • 3.1 自定义的注解
      • 3.2 创建的类
        • 3.3 创建的扩展类
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档