我有2个自定义注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface FlowPoint {
public enum PointInFlow {
START, END
}
PointInFlow pointInFlow();
}
和:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ScopeAnnotation {
public enum Category {
BUSINESS, DETECTION, INTERNAL_FUNC, THRESHOLD
}
Category category() default Category.DETECTION;
}
在我的代码中,我用PointInFlow.START
注释了一个方法,并用Category.DETECTION
和Category.BUSINESS
注释了其他方法
我的观点是:
@Pointcut("execution(* *(..)) && @annotation(flowPoint) && if()")
public static boolean executeStartMethod(<annotationPackage>.FlowPoint flowPoint) {
return flowPoint.pointInFlow() == FlowPoint.PointInFlow.START;}
@Before("executeStartMethod(flowPoint)")
public void beforeStartMethod(<annotationPackage>.FlowPoint flowPoint, JoinPoint jp) {
logger.infoBefore(jp, flowPoint.pointInFlow());}
@After("executeStartMethod(flowPoint)")
public void afterStartMethod(<annotationPackage>.annotation.FlowPoint flowPoint, JoinPoint jp) {
logger.infoAfter(jp);}
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeDetectionMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.DETECTION;}
@Before("executeDetectionMethod(scopeAnnotation)")
public void beforeDetectionMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoBefore(jp, scopeAnnotation.category());}
@After("executeDetectionMethod(scopeAnnotation)")
public void afterDetectionMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoAfter(jp);}
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeBusinessMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.BUSINESS;}
@Before("executeBusinessMethod(scopeAnnotation)")
public void beforeBusinessMethod(<annotationPackage>.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoBefore(jp, scopeAnnotation.category());}
@After("executeBusinessMethod(scopeAnnotation)")
public void afterBusinessMethod(<annotationPackage>.annotation.ScopeAnnotation scopeAnnotation, JoinPoint jp) {
logger.infoAfter(jp);}
问题是“检测”和“业务”分别工作((当我注释掉检测或业务切入点定义之一时)。)但并非如上所述。
提前感谢您的帮助
答案 0 :(得分:1)
您应该看到以下AspectJ编译错误:
circular advice precedence:
can't determine precedence between two or more pieces of advice that apply to the same join point:
method-execution(void de.scrum_master.app.Application.doEight())
作为解决方法,您可以执行以下操作:
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeDetectionOrBusinessMethod(ScopeAnnotation scopeAnnotation) {
return
scopeAnnotation.category() == ScopeAnnotation.Category.DETECTION ||
scopeAnnotation.category() == ScopeAnnotation.Category.BUSINESS;
}
@Before("executeDetectionOrBusinessMethod(scopeAnnotation)")
public void beforeDetectionOrBusinessMethod(ScopeAnnotation scopeAnnotation, JoinPoint jp) {
infoBefore(jp, scopeAnnotation.category());
}
@After("executeDetectionOrBusinessMethod(scopeAnnotation)")
public void afterDetectionOrBusinessMethod(ScopeAnnotation scopeAnnotation, JoinPoint jp) {
infoAfter(jp);
}
或者,如果您坚持将两个注释值的切入点和建议分开,只需在周围使用建议而不是之前/之后:
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeDetectionMethod(ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.DETECTION;
}
@Around("executeDetectionMethod(scopeAnnotation)")
public Object aroundDetectionMethod(ScopeAnnotation scopeAnnotation, ProceedingJoinPoint jp) throws Throwable {
infoBefore(jp, scopeAnnotation.category());
try {
return jp.proceed();
} finally {
infoAfter(jp);
}
}
@Pointcut("execution(* *(..)) && @annotation(scopeAnnotation) && if()")
public static boolean executeBusinessMethod(ScopeAnnotation scopeAnnotation) {
return scopeAnnotation.category() == ScopeAnnotation.Category.BUSINESS;
}
@Around("executeBusinessMethod(scopeAnnotation)")
public Object aroundBusinessMethod(ScopeAnnotation scopeAnnotation, ProceedingJoinPoint jp) throws Throwable {
infoBefore(jp, scopeAnnotation.category());
try {
return jp.proceed();
} finally {
infoAfter(jp);
}
}
答案 1 :(得分:0)
不确定如何解决您提出的问题,但是无论如何我还是建议进行重构。
您实际上对3个不同的注释执行了相同的操作,因此我将把不同的分支与一个调度程序合并为一个分支,并且可能会使用@Around
的建议,如@kriegaex所建议的。
我唯一想改变他的答案的方法是将两个@Around
通知的相同正文提取到一个通用方法。