gpt4 book ai didi

java - Spring AOP自定义注解,使用注解参数获取Null

转载 作者:行者123 更新时间:2023-12-02 11:39:36 27 4
gpt4 key购买 nike

我使用这个自定义注释来记录执行时间,注释可以出现在所有公共(public)方法都具有它的方法或类上。一切正常,除非方法级别“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());
}
}

当我们使用 OR '||' 时,希望理解这种行为有两个切入点。

类(class)级别

@LogExecutionTime
@Component
public class CleanUpService implements ICleanUpService { ... }

方法级别

@Scheduled(fixedDelay = 100)
@LogExecutionTime(false)
public void processMessageQueue() { ... }

最佳答案

我来运行你的示例,并重现与你的示例相同的示例,当涉及到运行时表达式时,它同样很奇怪,因为当你在类级别指定注释并编写此表达式时

@Around(" @within(logExecutionTime) || @annotation(logExecutionTime) ")

对于您的类,切入点将评估为 true(如果您注释其在 joinPoint.getTarget().getClass().getAnnotations() 中可用,)

现在,当涉及到绑定(bind)变量时,编译器会检查所有表示绑定(bind)的表达式 @within(logExecutionTime)变量 logExecutionTime 和 @annotation(logExecutionTime) 对于同一个变量,如果该方法没有注释,它将为 null,=> 覆盖初始 with,这会导致您提到的所有情况。

尝试输入此表达式 @within(logExecutionTime) || @annotation(logExecutionTime) || @within(logExecutionTime)你会得到变量 not null 这证明了我最后所说的 @within(logExecutionTime)覆盖先例

这里的关键是,用于选择切入点匹配的逻辑在上下文绑定(bind)时并不相同

现在,当谈到 AOP 切入点时,你必须小心并遵循他们提到的 Spring 团队的最佳实践 here以避免奇怪的运行时结果

干杯

关于java - Spring AOP自定义注解,使用注解参数获取Null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48678593/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com