Обработка исключений АОП
Я вижу, что Guice и Spring используют AOP Alliance под капотом для перехватов методов, и я пытался выяснить, как получить AOP Alliance для перехвата и обработки определенных исключений, поэтому мне не нужно писать один и тот же код снова и снова внутри каждого блока catch
.
Но после просмотра пьесы не похоже, что AOP Alliance предоставляет любой способ перехватить бросок Throwable
таким образом, что обработчик/перехватчик может делать некоторые вещи (регистрировать исключение и т.д.), а затем определить, следует ли распространять это исключение дальше или просто вернуться к следующей строке, следующей за строкой, которая выбрала исключение:
HerpDerp hd = null;
if(hd == null)
throw new RuntimeException("Herpyl derp!");
Manny.pacquiao();
Я ищу механизм обработки исключений AOP, который будет перехватывать RuntimeException
и использовать бизнес-логику, чтобы решить, продолжать ли распространять его или возвращаться к вызову Manny.pacquioa()
.
- Если это невозможно сделать на Java, сообщите мне
- Независимо от того, возможно ли это сделать на Java, есть ли способ перехватить исключение с AOP Alliance или мне нужно пойти куда-то еще. И если мне нужно пойти куда-нибудь еще, где? AspectJ?
Спасибо!
Ответы
Ответ 1
Вы можете перехватывать исключения с помощью Spring AOP, но я не знаю, соответствует ли это вашим требованиям для чистой среды Java.
С помощью Spring вы можете написать простой AOP-перехватчик как-то вроде:
@Aspect
public class ErrorInterceptor{
@AfterThrowing(pointcut = "execution(* com.mycompany.package..* (..))", throwing = "ex")
public void errorInterceptor(WidgetException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error Message Interceptor started");
}
// DO SOMETHING HERE WITH EX
logger.debug( ex.getCause().getMessage());
if (logger.isDebugEnabled()) {
logger.debug("Error Message Interceptor finished.");
}
}
}
но нет способа вернуться к вызывающему методу или продолжить обработку на следующей строке. Однако, если вы обрабатываете исключение здесь, оно не будет пузыриться по цепочке, если вы не восстановите ее самостоятельно.
Ответ 2
Есть причина, что этого не существует. Для этого потребуется переписать структуру блока вашего кода, как если бы вы вначале написали блок try/catch. Это, мне кажется, потенциально может привести к хаосу с переменным масштабом и другими вещами. Вы просите AOP переписать код байта как нечто похожее на следующий код, и это достаточно переписать.
HerpDerp hd = null;
try {
if(hd == null)
throw new RuntimeException("Herpyl derp!");
} catch(RuntimeException e) {
if (someConditionIsMet) {
throw e;
}
}
Manny.pacquiao();
Ответ 3
Чтобы "поймать" неперехваченные исключения с помощью AspectJ, вы можете использовать следующий аспект:
pointcut uncaughtExceptionScope() :
(execution(* com.mycompany.myrootpackage..Main.main(..))
|| execution(* java.util.concurrent.Callable+.call())
|| execution(* java.lang.Runnable+.run())
));
after() throwing(Throwable t) : uncaughtExceptionScope() && !cflow(adviceexecution()) {
handleException(thisJoinPoint, t);
}
protected void handleException(JoinPoint jp, Throwable t)
{
// handle exception here
}
Я не думаю, что можно "вернуться" к точке выполнения.
Ответ 4
@4herpsand7derpsago Если то, что вы пытаетесь сделать, - это поймать заброшенное исключение, используя AOP для выполнения различных задач для его обработки, а затем возвращается к коду, в котором первоначально было выбрано исключение, я думаю, вы не поняли концепцию AOP.
Как вы указываете в своем коде
HerpDerp hd = null;
if(hd == null)
throw new RuntimeException("Herpyl derp!");
Manny.pacquiao();
Если вы хотите, чтобы AOP поймал ваш RuntimeException
, выполните некоторые действия для его обработки и вернитесь к Manny.pacquiao();
, ответ вы не можете.
Причина в том, что, когда RuntimeException
выбрасывается и попадает в AOP, стек уже находится в вашем AOP-коде. вы не можете вернуться к выполнению Many.pacquiao();
. Единственный способ, если вы хотите продолжить выполнение Many.pacquiao();
, - это использовать блок try-finally
, как следует
HerpDerp hd = null;
try {
if(hd == null)
throw new RuntimeException("Herpyl derp!");
} finally {
Manny.pacquiao();
}
Только тогда ваш Many.pacquiao()
будет выполнен, но до того, как ваш AOP поймает RuntimeException