当试图实现一个负责捕获和记录某种类型错误的Aspect时,我最初认为这可以使用AfterThrowing建议。然而,似乎他的建议没有捕获异常,但只是提供了一个额外的入口点来做异常的事情。
唯一可以捕获有关异常的建议就是周围建议 - 或者我做错了。
任何人都可以断言,如果我想要捕获异常,我必须使用AroundAdvice吗?我使用的配置如下:
@Pointcut("execution(* test.simple.OtherService.print*(..))")
public void printOperation() {}
@AfterThrowing(pointcut="printOperation()", throwing="exception")
public void logException(Throwable exception) {
System.out.println(exception.getMessage());
}
@Around("printOperation()")
public void swallowException(ProceedingJoinPoint pjp) throws Throwable {
try {
pjp.proceed();
} catch (Throwable exception) {
System.out.println(exception.getMessage());
}
}
请注意,在此示例中,我捕获了所有异常,因为它只是一个示例。我知道只是吞下所有异常的坏习惯,但对于我当前的用例,我希望只记录一种特殊类型的异常,同时避免重复记录逻辑。
答案 0 :(得分:19)
Spring reference doc说:
“投掷建议后运行时 匹配的方法执行退出 抛出异常“
到那时,抓住异常已经太晚了,因为它已经被抛出并且方法已经退出。使用@Around建议的方法是实际捕获异常并在方法退出之前处理它的唯一方法。
答案 1 :(得分:0)
实际上,也可以在AfterThrowing建议中捕获异常。 我知道这是一个令人费解的示例,但它可以工作。
@Aspect
@Component
class MyAspect {
@Autowired
public Worker worker;
@Pointcut(value = "execution(public * com.ex*..*.*(..))")
public void matchingAll(){}
@AfterThrowing(pointcut = "matchingAll()", throwing = "e")
public void myAdvice(RuntimeException e){
Thread.setDefaultUncaughtExceptionHandler((t, e1) ->
System.out.println("Caught " + e1.getMessage()));
System.out.println("Worker returned " + worker.print());
}
}
@Component
class Worker {
public static int value = 0;
public int print() {
if (value++ == 0) {
System.out.println("Throwing exception");
throw new RuntimeException("Hello world");
} else {
return value;
}
}
}
@SpringBootApplication
@EnableAspectJAutoProxy
public class AdvicesDemo {
public static void main(String[] args) {
final ConfigurableApplicationContext applicationContext = SpringApplication.run(AdvicesDemo.class);
final Worker worker = applicationContext.getBean(Worker.class);
System.out.println("Worker returned " + worker.print());
System.out.println("All done");
}
}
如您所见,它更多地是关于如何捕获最初引发的异常,从而防止其传播回调用者的。
GitHub上的工作示例(请查看com.example.advices软件包)