Обработка исключений АОП - программирование
Подтвердить что ты не робот

Обработка исключений АОП

Я вижу, что 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?

Спасибо!

4b9b3361

Ответ 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