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;
}
}
问题在于,对于MyOwnException
和RuntimeException
的其他祖先,在这两种情况下都执行AspectTwo
。如何限制AspectTwo
仅在AspectOne
未捕捉到异常时执行?
似乎@Order
注释并没有像我预期的那样工作。
用一个小技巧来表示已经处理/建议了异常如何?
还要注意的是,执行的顺序在这里是AspectTwo
之前的AspectOne
,对于AspectOne
,Order
应该被指定为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);
}
}
具有修改的Order
的AspectOne
和添加抑制异常的逻辑。
@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;
}
}