AOP获取加在方法上的自定义注解的注意事项
  TEZNKK3IfmPf 13天前 19 0

需求:在Mapper层中添加/更新数据操作,需要对应修改表字段的创建时间/最后修改时间

需求分析:可以给Mapper层中的新增/修改方法添加自定义注解,然后使用AOP的前置通知,在通知内通过反射获取到Mapper层中的方法对象,再获取到方法上的注解,再根据注解的值进行对应的操作。新增数据,设置创建时间、最后修改时间;修改数据,设置最后修改时间。

方式一

    @Before("切点表达式")
    public void before1(JoinPoint jp) {
     
       
        // 先拿到被增强的方法的签名对象
        Signature signature = jp.getSignature();

        // 判断被增强的目标是否是一个方法 如果是进行强转
        if (!(signature instanceof MethodSignature)) {
     
       
        	// 如果不是抛出自定义异常
            throw Exception.throwException(ErrorEnums.AOP_ADVICE_ERROR);
        }

        MethodSignature ms = (MethodSignature) signature;

        // 拿到目标方法
        Method method = ms.getMethod();

        // 获取method上的注解 并且拿到注解上的value值,AutoFill.class为自定义注解类
        AutoFill annotation = method.getAnnotation(AutoFill.class);

		// 如果注解为空,抛出自定义异常
        if (ObjUtil.isNull(annotation)) {
     
       
            throw SkyException.throwException(ErrorEnums.AOP_ADVICE_ERROR);
        }

		// 获取注解的值
        String value = annotation.value();
        
		// 如果注解为空,抛出自定义异常
        if (ObjUtil.isNull(jp.getArgs()) || ArrayUtil.isEmpty(jp.getArgs())) {
     
       
            throw Exception.throwException(ErrorEnums.AOP_ADVICE_ERROR);
        }

        // 获取参数
        Object arg = jp.getArgs()[0];

		// 增加注解的方法都执行的操作,如新增数据的创建时间(createTime)字段
        ReflectUtil.setFieldValue(arg, "updateTime", LocalDateTime.now());

		// 如果注解值==标志,如“UPDATE”(更新),则进行更新操作
        if (StrUtil.equalsIgnoreCase(value, "INSERT")) {
     
       
        
        	// 设置需要更新字段
            ReflectUtil.setFieldValue(arg, "createTime", LocalDateTime.now());
			……
        }
    }

方式二

    @Before("切点表达式")
    public void before2(JoinPoint jp) throws NoSuchMethodException {
     
       

        // 先拿到被增强的方法的签名对象
        Signature signature = jp.getSignature();

        // 判断被增强的目标是否是一个方法 如果是进行强转
        if (!(signature instanceof MethodSignature)){
     
       
             // 如果不是抛出自定义异常
            throw new Exception(ErrorEnums.AOP_ADVICE_ERROR);
        }

        MethodSignature ms = (MethodSignature) signature;

		// 获取代理方法对象
        Class<?> aClass = jp.getTarget().getClass();

		// 根据方法名、方法参数获取代理类中的方法对象
        Method method = aClass.getMethod(ms.getName(), ms.getParameterTypes());

		// 获取方法上的注解,AutoFill.class为自定义注解类
        AutoFill annotation = method.getAnnotation(AutoFill.class);

		// 如果注解为空,抛出自定义异常
        if (ObjUtil.isNull(annotation)){
     
       
            throw new Exception(ErrorEnums.AOP_ADVICE_ERROR);
        }

		// 获取注解的值
        String value = annotation.value();

		// 增加注解的方法都执行的操作,如新增数据的创建时间(createTime)字段
        ReflectUtil.setFieldValue(method,"createTime",LocalDateTime.now());
        
		// 如果注解值==标志,如“UPDATE”(更新),则进行更新操作
        if (StrUtil.equalsIgnoreCase(value,"UPDATE")){
     
       
        
			// 设置需要更新字段
			ReflectUtil.setFieldValue(method,"updateTime",LocalDateTime.now())
			……
        }
    }

区别&分析

将断点打在获取注解的后一行,查看method、annotation的内容

区别

方式一

AOP获取加在方法上的自定义注解的注意事项

AOP获取加在方法上的自定义注解的注意事项


方式二

AOP获取加在方法上的自定义注解的注意事项

AOP获取加在方法上的自定义注解的注意事项

观察可以发现,区别在于方式一获取到的是Mapper中的方法(即定义的接口方法)对象,方式二获取到的是MyBatis通过代理帮助我们实现Mapper类的实现方法对象

然后,因为我们AOP的注解是加在Mapper类中的抽象方法上的,所以通过方式二,是获取不到我们自定义的注解的

总结

使用AOP对方法增强,如果自定义注解是加在一般方法上,两者没有区别;

但如果需要增强的目标方法是Mapper里面的方法,因为Mybatis对方法进行了实现,则使用第二种方法,是获取不到我们自定义的注解的,因为方式二获取到的是实现类的方法对象,而实现类的方法对象是没有我们加的自定义注解的。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 13天前 0

暂无评论

推荐阅读
TEZNKK3IfmPf