@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.使用总结
关于多个注解的使用总结如下:
拦截注解 | 使用注解个数 | getAnnotation | getAnnotationsByType |
---|---|---|---|
@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只拦截一次,不会因为多个注解而拦截多次,这是和不同注解作用于一个方法不同