Spring AOP 不能双重绑定注解
Spring AOP can't double bind annotation
我有注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Retry {
int DEFAULT_RETRIES = 2;
int times() default DEFAULT_RETRIES;
}
在 class 级别上使用:
@Retry(times = 5)
public class PersonServiceClass {
//...
public void deletePerson(long id) {
//...
}
}
或者方法级别(另一个class,不是PersonServiceClass):
@Retry
public void deletePerson(long id) {
//...
}
方面被这样抓class:
@Aspect
@Component
public class RetryInterceptor {
@Around("@within(retry) || @annotation(retry)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, Retry retry) throws Throwable {
System.out.println("around - " + retry);
System.out.println("joinpoint - " + proceedingJoinPoint);
return aroundHandler(proceedingJoinPoint, retry);
}
方面在方法或 class 级别上正确捕获,但绑定 Retry
注释有问题。
当@Around
如下:@Around("@within(retry) || @annotation(retry)")
则:
- 当在方法级别捕获时,
retry
被 绑定
- 当在 class 水平上捕获时
retry
是 null。
当@Around
如下@Around("@annotation(retry) || @within(retry)")
则:
- 当在方法级别捕获时,
retry
为 null。
- 当在 class 水平上被捕获时,
retry
被 绑定。
Spring 引导父版本 - 2.1.1.RELEASE
...现在你向我发起挑战:) 而我 could reproduce the issue!
务实地我(会)这样解决(d)它:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ExampleAspect {
@Around("@within(retry)")
public Object typeAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
return commonAspect(joinPoint, retry);
}
@Around("@annotation(retry)")
public Object methodAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
return commonAspect(joinPoint, retry);
}
private Object commonAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
System.out.println("Retry is :" + (retry == null ? "null" : retry.value()));
// ... do your (common) stuff here
return proceed;
}
}
..欢迎! :-)
并且由于您已经有了一个(通用的)aroundHandler()
方法,所以它归结为 "introducing 2 public facades/PCDs for it"。
附加提示:将 times()
(如果它是该注释的 only/main 属性)重命名为:value()
! ..然后你可以做 "just" @Retry(100)
.
我有注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Retry {
int DEFAULT_RETRIES = 2;
int times() default DEFAULT_RETRIES;
}
在 class 级别上使用:
@Retry(times = 5)
public class PersonServiceClass {
//...
public void deletePerson(long id) {
//...
}
}
或者方法级别(另一个class,不是PersonServiceClass):
@Retry
public void deletePerson(long id) {
//...
}
方面被这样抓class:
@Aspect
@Component
public class RetryInterceptor {
@Around("@within(retry) || @annotation(retry)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, Retry retry) throws Throwable {
System.out.println("around - " + retry);
System.out.println("joinpoint - " + proceedingJoinPoint);
return aroundHandler(proceedingJoinPoint, retry);
}
方面在方法或 class 级别上正确捕获,但绑定 Retry
注释有问题。
当@Around
如下:@Around("@within(retry) || @annotation(retry)")
则:
- 当在方法级别捕获时,
retry
被 绑定 - 当在 class 水平上捕获时
retry
是 null。
当@Around
如下@Around("@annotation(retry) || @within(retry)")
则:
- 当在方法级别捕获时,
retry
为 null。 - 当在 class 水平上被捕获时,
retry
被 绑定。
Spring 引导父版本 - 2.1.1.RELEASE
...现在你向我发起挑战:) 而我 could reproduce the issue!
务实地我(会)这样解决(d)它:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ExampleAspect {
@Around("@within(retry)")
public Object typeAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
return commonAspect(joinPoint, retry);
}
@Around("@annotation(retry)")
public Object methodAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
return commonAspect(joinPoint, retry);
}
private Object commonAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
System.out.println("Retry is :" + (retry == null ? "null" : retry.value()));
// ... do your (common) stuff here
return proceed;
}
}
..欢迎! :-)
并且由于您已经有了一个(通用的)aroundHandler()
方法,所以它归结为 "introducing 2 public facades/PCDs for it"。
附加提示:将 times()
(如果它是该注释的 only/main 属性)重命名为:value()
! ..然后你可以做 "just" @Retry(100)
.