我知道您想避免使用完整的 AspectJ 而不是 Spring AOP。handler()
(顺便说一句,我想知道为什么很多人这么害怕它。)无论如何,在 AspectJ 中,通过切入点拦截异常处理程序执行(=catch 块)真的很容易。但是有一个限制:它只适用于before()
建议,而不是after()
or around()
。这是由于编译器的限制。查看异常处理程序的 JVM 字节码,您会发现无法检测处理程序块的结束。无论如何,因为这个概念与原始问题有关,所以我想在这里展示它是如何完成的。我创建了一个小驱动程序应用程序和一个非常简单的方面:
import java.util.Random;
import javax.naming.AuthenticationException;
public class Application {
public static void main(String[] args) {
Application app = new Application();
System.out.println(app.foo(1, "two", 3d));
System.out.println(app.bar("one", 2d, 3));
System.out.println(app.zot(1d, 2, "three"));
}
public String foo(int i, String string, double d) {
try {
if (new Random().nextBoolean())
throw new AuthenticationException("wrong password");
}
catch (AuthenticationException e) {
return "return value from catch block";
}
return "normal return value";
}
public String bar(String string, double d, int i) {
try {
if (new Random().nextBoolean())
throw new IllegalArgumentException("I don't like your arguments");
}
catch (IllegalArgumentException e) {
return "return value from catch block";
}
return "normal return value";
}
public String zot(double d, int i, String string) {
try {
int n = 2/0;
}
catch (Throwable t) {
return "return value from catch block";
}
return "normal return value";
}
}
如您所见,方法foo
和bar
抛出异常基于 ca. 50% 的情况,而zot
总是抛出除以零异常。所以输出会因运行而异。
那么,如果所有异常都被默默吞下并且没有记录下来,我们如何找出发生了什么?像这样:
import java.util.logging.Logger;
public aspect ExceptionLoggingAspect {
final Logger log = Logger.getLogger(ExceptionLoggingAspect.class.getName());
before(Throwable t) : handler(Throwable+) && args(t) {
log.warning(thisJoinPointStaticPart + " -> " + t);
}
}
这非常简单而优雅,并且适用于您的整个应用程序。这是一些测试输出:
Apr 6, 2013 12:15:43 PM ExceptionLoggingAspect ajc$before$ExceptionLoggingAspect$1$3d90b181
WARNING: handler(catch(AuthenticationException)) -> javax.naming.AuthenticationException: wrong password
return value from catch block
Apr 6, 2013 12:15:43 PM ExceptionLoggingAspect ajc$before$ExceptionLoggingAspect$1$3d90b181
WARNING: handler(catch(IllegalArgumentException)) -> java.lang.IllegalArgumentException: I don't like your arguments
return value from catch block
Apr 6, 2013 12:15:43 PM ExceptionLoggingAspect ajc$before$ExceptionLoggingAspect$1$3d90b181
WARNING: handler(catch(Throwable)) -> java.lang.ArithmeticException: / by zero
return value from catch block
在建议中,您可以做更多事情,例如访问this
和读取/更新某些属性等等。