弹簧启动 2 在方面找到成功或失败之后



我正在 Spring Boot 2 上创建一个微服务。我需要创建一个After方面来执行一些代码。

@Aspect
@Component
public class FinallyAspect {
@Pointcut("@annotation(finallyEvent)")
public void runFinallyMethod(FinallyEvent finallyEvent) {}
@After("runFinallyMethod(FinallyEvent finallyEvent)")
public void finallyMethod(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable { 
// ...
}
}

是否可以深入了解是否发生了异常或成功返回finallyMethod方法?我可以使用@AfterReturning@AfterThrowing注释来做到这一点,但是如果有一种方法可以检查该方法是否以错误或成功告终,那么我可以在单个函数中进行检查。

使用 After-advice无法访问该方法是成功返回还是返回异常。还有其他选择...

a)Around-advice(不推荐)

您想要的内容可以使用Around-advice(最通用的建议)使用单一方法手动实现。建议您使用可以实现所需行为(源)的最不强大的建议类型。我不推荐这种方法,因为如果以错误的方式实施,它在异常处理方面可能容易出错。例如,如果将成功代码放在 try-block 中,则此成功代码引发的异常也会被用于失败代码的同一 catch 块捕获。此外,您需要确保重新引发异常并返回joinPoint.proceed()的返回值。

如果您想执行以下操作,这就是如何正确执行此操作的方法:

@Around(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public Object finallyMethod(ProceedingJoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
final Object res;
try {
res = joinPoint.proceed();
} catch (Throwable e) {
// code in case of failure
throw e;
}
// code in case of success
return res;
}

b) 使用私有方法的清洁解决方案

在这种情况下,我建议使用AfterReturning-advice 和 AfterThrowing-advice,然后调用一个带有指示成功/错误的参数的私有方法。这更具可读性,没有Around-advice的缺点,但使用了更多的代码。

需要布尔值 (success)

@AfterReturning(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public void finallyMethodReturning(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
finallyMethod(joinPoint, finallyEvent, true);
}
@AfterThrowing(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public void finallyMethodThrowing(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
finallyMethod(joinPoint, finallyEvent, false);
}
private void finallyMethod(JoinPoint joinPoint, FinallyEvent finallyEvent, boolean success) throws Throwable {
if (success) {
// code in case of success
} else {
// code in case of failure
}
}

需要Throwable

@AfterReturning(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public void finallyMethodReturning(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
finallyMethod(joinPoint, finallyEvent, null);
}

@AfterThrowing(value = "runFinallyMethod(finallyEvent)", throwing = "t", argNames = "joinPoint,finallyEvent,t")
public void finallyMethodThrowing(JoinPoint joinPoint, FinallyEvent finallyEvent, Throwable t) throws Throwable {
finallyMethod(joinPoint, finallyEvent, t);
}
private void finallyMethod(JoinPoint joinPoint, FinallyEvent finallyEvent, Throwable t) throws Throwable {
if (t == null) {
// code in case of success
} else {
// code in case of failure
}
}

我认为您将无法使用@After实现这一点,因为此注释只能在上下文中为您提供JoinPoint,其中没有有关返回值的信息。

如果您想在同一方法中处理所有内容,我认为唯一的选择是使用@Around来实现这一点,您可以在方法执行之前和之后执行一些操作。您的实现可以是:

@Around("runFinallyMethod(FinallyEvent finallyEvent)")
public Object finallyMethod(ProceedingJoinPoint jp, FinallyEvent finallyEvent) throws Throwable { 
try {
Object result = jp.proceed();
// do nice stuff with result
return result;
} catch(Throwable throwable) {
// do nice stuff with the exception;
throw throwable;
}
}

最新更新