同一个方法上多个自定义注解的执行顺序问题分析

文章讨论了在社交化电商项目中,如何通过自定义注解A和B实现敏感词和黑名单拦截。实验发现,注解名称小的在注解A和B同时存在时会先执行,且通过@Order注解可以明确指定执行顺序,确保黑名单拦截先于敏感词拦截。
摘要由CSDN通过智能技术生成

需求背景

在社交化电商项目中,除了需要对用户提交的敏感词进行拦截,也需要对黑名单用户进行拦截。因此,项目通过自定义注解的方式实现了两个注解@TextBlock和@BlackBlock,并实现了对应的拦截处理。

当笔者将两个注解注释在同一个方法(比如:用户发布帖子)上时,突然意识到一个问题:这两个注解的处理逻辑谁先谁后?笔者项目中的业务逻辑:黑名单拦截必须在敏感词拦截之前。

问题分析

针对上述问题,有两种观点:
(1)按照注解标注的顺序先后执行对应的拦截逻辑;
(2)按照注解名称的大小(以字符串形式进行比较),小的先执行,大的后执行;

接下来我们一起来看实践一下,实践出真知。

先定义两个注解和对应的切面类

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface A {
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface B {
}

@Slf4j
@Aspect
@Component
public class AAspect {
    @SneakyThrows
    @Around("@annotation(a)")
    public Object around(ProceedingJoinPoint point, A a) {
        log.info("注解A拦截处理");
        return point.proceed();
    }
}

@Slf4j
@Aspect
@Component
public class BAspect {
    @SneakyThrows
    @Around("@annotation(b)")
    public Object around(ProceedingJoinPoint point, B b) {
        log.info("注解B拦截处理");
        return point.proceed();
    }
}

再定义一个Service类来使用这些注解,代码如下:

@Component
@Slf4j
public class AbService {

	@B
	@A
	public void ab() {
		log.info("======ab======");
	}
}

请注意:上述代码中@B标注在@A之前,执行结果如下:

注解A拦截处理
注解B拦截处理
======ab======

由此,我们可以断定第1个观点时错误的。

接下来,我们将@A和@B交换注释位置之后,执行结果仍然不变。

注解A拦截处理
注解B拦截处理
======ab======

由此,我们可以推出第2个观点是正确的。

那如果想让@B先执行呢?就如电商中实际的需求,黑名单拦截必须先于敏感词拦截执行。

在注解对应的Aspect类上使用@Order注解指定执行顺序,指定值越小越先执行。如未指定,默认值为Integer.MAX_VALUE,即2147483647。

@Slf4j
@Aspect
@Component
@Order(10000)
public class BAspect {
    @SneakyThrows
    @Around("@annotation(b)")
    public Object around(ProceedingJoinPoint point, B b) {
        log.info("注解B拦截处理");
        return point.proceed();
    }
}

在BAspect类上加上注解@Order(10000),由于10000小于AAspect默认的顺序Integer.MAX_VALUE,因此该逻辑会先执行。执行结果如下:

注解B拦截处理
注解A拦截处理
======ab======

问题结论

  • 同一个方法上多个自定义注解,如果对应的切面类顺序相同,则注解名称小的先执行。默认情况注解A的逻辑优先注解B的逻辑;
  • 如果通过@Order指定了切面类顺序,则顺序值越小越先执行。

参考文档

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据提供的引用内容,没有明确说明Spring Boot自定义注解执行顺序。但是,我们可以通过以下步骤来实现自定义注解执行顺序: 1. 定义多个自定义注解,并为每个注解指定一个执行顺序的值。 2. 创建一个注解处理器类,使用@Order注解指定该处理器的执行顺序。 3. 在注解处理器类中,使用@Priority注解指定处理器的执行顺序。 4. 在处理器类中,使用@Around注解指定处理器的执行方法,并在方法中使用ProceedingJoinPoint参数来控制注解执行顺序。 下面是一个示例代码,演示了如何实现自定义注解执行顺序: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface FirstAnnotation { int order() default 1; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SecondAnnotation { int order() default 2; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ThirdAnnotation { int order() default 3; } @Aspect @Component public class AnnotationAspect { @Around("@annotation(com.example.demo.FirstAnnotation) || @annotation(com.example.demo.SecondAnnotation) || @annotation(com.example.demo.ThirdAnnotation)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Annotation[] annotations = method.getAnnotations(); Arrays.sort(annotations, new Comparator<Annotation>() { @Override public int compare(Annotation o1, Annotation o2) { int order1 = getOrder(o1); int order2 = getOrder(o2); return order1 - order2; } private int getOrder(Annotation annotation) { if (annotation instanceof FirstAnnotation) { return ((FirstAnnotation) annotation).order(); } else if (annotation instanceof SecondAnnotation) { return ((SecondAnnotation) annotation).order(); } else if (annotation instanceof ThirdAnnotation) { return ((ThirdAnnotation) annotation).order(); } return 0; } }); for (Annotation annotation : annotations) { System.out.println(annotation.annotationType().getSimpleName() + " is executed."); } return joinPoint.proceed(); } } ``` 在上面的代码中,我们定义了三个自定义注解:FirstAnnotation、SecondAnnotation和ThirdAnnotation,并为每个注解指定了一个执行顺序的值。然后,我们创建了一个注解处理器类AnnotationAspect,并使用@Order注解指定了该处理器的执行顺序。在处理器类中,我们使用@Around注解指定了处理器的执行方法,并在方法中使用ProceedingJoinPoint参数来控制注解执行顺序。最后,我们使用Arrays.sort方法注解进行排序,并按照指定的执行顺序依次执行注解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧十一郎君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值