Spring AOP异常处理程序-只执行排序中的第一个方面



UPD我已经更新了Aspects的代码,以进一步引发异常

我有SpringBoot应用程序、服务类,我需要为我的服务实现异常处理程序(而不是MVC(。任务是记录错误并将其进一步抛出到客户端。

我决定将Aspect与@AfterThrowing建议一起使用。我将在AspectOne方面发现一些异常(扩展了RuntimeException(。对于其他情况,我需要在AspectTwo方面捕获异常(扩展RuntimeException(。

所以我做了以下代码:

public class MyOwnException extends RuntimeException {
}
@Aspect
@Order(0)
@Component
public class AspectOne {
@Pointcut("execution(* com.test.MyService.*(..))")
public void logException() {}
@AfterThrowing(pointcut="logException()", throwing="ex")
public void logException(MyOwnException ex) {
System.out.println("MyOwnException has been thrown: " + ex.getMessage());
throw ex;
}
}
@Aspect
@Order(1)
@Component
public class AspectTwo {
@Pointcut("execution(* com.test.MyService.*(..))")
public void logException() {}
@AfterThrowing(pointcut="logException()", throwing="ex")
public void logException(RuntimeException ex) {
System.out.println("Some unknown exception has been thrown: " + ex);
throw ex;
}
} 

问题在于,对于MyOwnExceptionRuntimeException的其他祖先,在这两种情况下都执行AspectTwo。如何限制AspectTwo仅在AspectOne未捕捉到异常时执行?

似乎@Order注释并没有像我预期的那样工作。

用一个小技巧来表示已经处理/建议了异常如何?

还要注意的是,执行的顺序在这里是AspectTwo之前的AspectOne,对于AspectOneOrder应该被指定为1,而对于AspectTwo,则应该指定为0。

参考文件部分:建议订购

当多条建议都想在相同的连接点Spring AOP遵循与AspectJ来确定建议执行的顺序。最高优先建议先运行";在";(因此,给定两块在建议之前,优先级最高的先运行("关于出路";从连接点开始,优先级最高的建议运行在最后(因此,给出了两条事后建议,其中一条建议最高优先级将排在第二位(。

以下代码利用Throwable.addSuppressed((方法来指示异常对象已被处理/建议。

--

添加一个Exception类以用作指示符。

public class AlreadyAdvicedIndicator extends Exception {
private static final long serialVersionUID = 1L;

public AlreadyAdvicedIndicator(String message) {
super(message);
}
}

具有修改的OrderAspectOne和添加抑制异常的逻辑。

@Component
@Aspect
@Order(1)
public class AspectOne {
public static final String ALREADY_ADVICED_MSG="Adviced with AspectOne";

private static final AlreadyAdvicedIndicator alreadyAdviced = new AlreadyAdvicedIndicator(ALREADY_ADVICED_MSG);
@Pointcut("execution(* com.test.MyService.*(..))")
public void logException() {}
@AfterThrowing(pointcut="logException()", throwing="ex")
public void logException(MyOwnException ex) {
System.out.println("MyOwnException has been thrown: " + ex.getMessage());
ex.addSuppressed(alreadyAdviced);
}
}

具有修改的CCD_ 20的AspectTwo和用于检查是否已经建议的逻辑。

@Component
@Aspect
@Order(0)
public class AspectTwo {
@Pointcut("execution(* com.test.MyService.*(..))")
public void logException() {
}
@AfterThrowing(pointcut = "logException()", throwing = "ex")
public void logException(RuntimeException ex) {
if (isAlreadyAdviced(ex)) {
System.out.println("Already Adviced : Skipping");
} else {
System.out.println("RuntimeException has been thrown: " + ex.getMessage());
}
}
private boolean isAlreadyAdviced(RuntimeException ex) {
for(Throwable e : ex.getSuppressed()) {
if(AspectOne.ALREADY_ADVICED_MSG.equals(e.getMessage())){
return true;
}
}
return false;
}
}

最新更新