我正在使用此自定义注释来记录执行时间,可以在所有公共方法拥有的方法或类上存在注释。一切正常,除了方法级别" logexecutiontime logexecutiontime"之外。这会抛出NPE。
@Around("@annotation(logExecutionTime) || @within(logExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
final Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
final String name = joinPoint.toShortString();
final StopWatch stopWatch = new StopWatch(name);
stopWatch.start(name);
try {
return joinPoint.proceed();
} finally {
stopWatch.stop();
if (logExecutionTime.value()) {
logger.info(joinPoint.getSignature().getName() + ".time=", stopWatch.getTotalTimeSeconds());
}
}
}
如果我扭转了订单 -
@Around("@within(logExecutionTime) || @annotation(logExecutionTime)")
行为逆转,我在方法级别获得了一个有效的对象,而在类级别注释的方法为null。
我通过使用2种明确的方法并分开两个
来解决这个问题。@Around("@within(logExecutionTime)")
public Object logExecutionTimeClassLevel(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
return logExecutionTimeMethodLevel(joinPoint, logExecutionTime);
}
@Around("@annotation(logExecutionTime)")
public Object logExecutionTimeMethodLevel(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
final Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
final String name = joinPoint.toShortString();
final StopWatch stopWatch = new StopWatch(name);
stopWatch.start(name);
try {
return joinPoint.proceed();
} finally {
stopWatch.stop();
if (logExecutionTime.value()) {
logger.info(joinPoint.getSignature().getName() + ".time=", stopWatch.getTotalTimeMillis());
}
}
当我们使用或'||'时,希望理解这种行为带有两个点数。
类级
@LogExecutionTime
@Component
public class CleanUpService implements ICleanUpService { ... }
方法级
@Scheduled(fixedDelay = 100)
@LogExecutionTime(false)
public void processMessageQueue() { ... }
我来运行您的示例,并重现与您的示例相同的示例,当涉及到运行时表达式是相同的怪异时/p>
@Around(" @within(logExecutionTime) || @annotation(logExecutionTime) ")
cut cut将对您的班级进行评估(事件您的注释在joinPoint.getTarget().getClass().getAnnotations()
中可用(
现在,当涉及到变量时,编译器检查您的所有表达式,这意味着将@within(logExecutionTime)
绑定到变量logexecution Time和@annotation(logExecutionTime)
与同一变量>>覆盖最初的,这是您提到的所有senarios。
尝试放置此表达式@within(logExecutionTime) || @annotation(logExecutionTime) || @within(logExecutionTime)
而且您将使您的变量不是null证明我所说的,最后@within(logExecutionTime)
覆盖了什么先例
这里的关键是,逻辑应用于上下文结合
时,选择点剪切匹配不相同现在,当涉及到aop cut时,您必须小心并遵循最佳练习,因为他们在这里提到的春季团队以避免怪异的运行时结果
欢呼
这是无法工作的,它甚至不会与ActectJ编译器进行编译。也许在您的IDE和春季AOP中,您看不到任何警告或错误,但我看到:
ambiguous binding of parameter(s) logExecutionTime across '||' in pointcut
这意味着尚不清楚如果例如,应该选择哪个注释。类和方法都包含该注释的实例。正如错误消息所说,这是模棱两可的。但是不允许跨||
的模棱两可的参数绑定。如果您尝试将不同的"或"分支与args()
列表中的单个参数绑定到单个参数时,它们也可能发生。
我也有同样的问题。您想要的与Spring @Transcriptional的行为完全相同(我的意思是,使用参数的类级或方法级别注释(。我使用了您的解决方案,但要获取类级别参数值(作为接收到null的注释对象(,我使用了反射。我知道这是一个肮脏的解决方案!但是我尝试了其他解决方案,找不到!
她是完整的代码。这将调用咨询代码的注释在类或方法上使用。如果将注释放在(类和方法(上,则该方法采用优先级。
@Aspect
@Configurable
@Component
public class DynamicValueAspect {
@Around(" @within(dynamicValueAnnotation) || @annotation(dynamicValueAnnotation))")
public Object process(ProceedingJoinPoint joinPoint, DynamicValue dynamicValueAnnotation) throws Throwable {
String annotationParameter;
if (dynamicValueAnnotation == null) { //class level annotation
annotationParameter = extractClassLevelAnnotationParameterValue(joinPoint);
} else {
annotationParameter = dynamicValueAnnotation.myAnnotationParameter();
}
System.out.println(" " + annotationParameter);//get the annotation parameter value
return joinPoint.proceed();
}
private String extractClassLevelAnnotationParameterValue(ProceedingJoinPoint joinPoint) {
Annotation[] classAnnotations = joinPoint.getTarget().getClass().getAnnotations();
for (Annotation annotation : classAnnotations) {
if (annotation.annotationType() == DynamicValue.class) {
return ((DynamicValue) annotation).myAnnotationParameter();
}
}
throw new RuntimeException("No DynamicValue value annotation was found");
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface DynamicValue {
String myAnnotationParameter();
}
让我们知道您是否有更清洁的解决方案!
当您注释一类带注释的方法和方法时出现解决方法的问题,从而触发了两个。
防止其声明班级建议为:
@Around("!@annotation(LogExecutionTime) && @within(logExecutionTime)")