Я знаю, что вы хотите избежать полного AspectJ в отличие от Spring AOP. (Кстати, мне интересно, почему многие люди так этого боятся.) В любом случае, в AspectJ действительно легко перехватить выполнение обработчика исключений (= блоки catch) с помощью handler()
pointcut. Однако есть одно ограничение: он работает только с before()
советом, но не с after()
или 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
генерируют исключения на основе случайных значений в ок. 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
и чтение / обновление некоторых свойств и т. д.
person
kriegaex
schedule
06.04.2013
req
и почему / где вы должны делать что-нибудь статичное? Пожалуйста, предоставьте минимальный образец кода с одним или двумя классами и кодом вашего аспекта, воспроизводящим вашу проблему, чтобы мы могли ее понять. В противном случае я понятия не имею, как тебе помочь. - person kriegaex   schedule 18.03.2013