@Repeatable与重复注解的使用

1. @Repeatable注解

@Repeatable是JDK1.8出现的元注解,在早前的版本中声明的注解Annotation是不能够重复作用在同一个类或方法上的,而有些时候我们的开发偏偏需要这样的使用诉求和场景。

2.@Repeatable使用

单一注解的使用方式如下:

/**
 * created by guanjian on 2020/11/30 19:58
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Aop {

    String value() default "";
}

引入@Repeatable注解后,改造如下:

/**
 * created by guanjian on 2020/11/30 19:58
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(Aops.class) //这里作用在业务注解上
public @interface Aop {

    String value() default "";
}

引入了@Aops返回@Aop数组以支持@Aop多次注解重复使用

/**
 * created by guanjian on 2020/11/30 19:58
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Aops {

    Aop[] value(); //这里返回的是业务注解@Aop的数组
}

3.Aspect切面

/**
 * created by guanjian on 2020/11/30 20:00
 */
@Aspect
@Component("aopAspect")
public class AopAspect {

    @Resource
    private TransactionTemplate transactionTemplate;
	
    @Around("@annotation(com.github.java.learning.spring.aop.annotation.Aop) " +
            "|| @annotation(com.github.java.learning.spring.aop.annotation.Aops)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Aop[] aops = getMethod(pjp).getAnnotationsByType(Aop.class);
        Stream.of(aops).forEach(x->{
            System.out.format("value=== %s\n", x.value());
        });

        return pjp.proceed();
    }

    protected Method getMethod(ProceedingJoinPoint pjp) {
        Method method = null;
        try {
            MethodSignature ms = (MethodSignature) pjp.getSignature();
            method = pjp.getTarget()
                    .getClass()
                    .getMethod(ms.getName(), ms.getParameterTypes());
        } catch (NoSuchMethodException e) {
            //ignore
        }
        return method;
    }
}

4.Service方法

/**
 * created by guanjian on 2020/11/30 20:13
 */
@Component("aopService")
public class AopService {

    @Aop("a")
    @Aop("c")
    @Aop("b")
    public Object test(User req) {
        return new Object();
    }
}

5.使用总结

关于多个注解的使用总结如下:

拦截注解使用注解个数getAnnotationgetAnnotationsByType
@Aop单个
@Aop多个××
@Aops单个××
@Aops多个×
@Aop + @Aops单个
@Aop + @Aops多个×
  • 使用的时候,为了支持单个和多个的可扩展性,@Around配置同时拦截@Aop和@Aops,通过getAnnotationsByType获取注解数组来获取注解对象进行逻辑操作

  • 通过getAnnotationsByType获取到的 Annotation[] 注解数组也是按照方法的存放顺序由上到下存储的,是有顺序性的,比如按照@Aop(“a”)、@Aop(“c”)、@Aop(“b”)进行配置,则拿到a、c、b的Annotation对象

  • 业务方法被多个相同注解使用,只在一个Aspect切面中使用一次,也就是说Service方法执行一次,Aspect只拦截一次,不会因为多个注解而拦截多次,这是和不同注解作用于一个方法不同
    在这里插入图片描述

posted @ 2020-12-04 14:01  大摩羯先生  阅读(147)  评论(0编辑  收藏  举报