Aspectj "после броска" - отслеживать конкретное исключение

Я пытаюсь поймать все исключения MySpecificException, выброшенные из кода приложения через aspectj.

Есть много мест, где это исключение может быть выброшено. Как только исключение выдается, я хочу зарегистрировать его или выполнить какую-либо операцию (независимо от того, было ли оно перехвачено позднее или нет).

Я пытался использовать:

@AfterThrowing(value = "(execution(* *.*(..))), throwing = "throwable")

но это перебор, так как он ловит все исключения. Я могу фильтровать вручную позже, но я пытаюсь избежать этого (из-за природы моих приложений, в некоторых случаях это вызывает проблемы со временем загрузки из-за проблем с загрузчиком классов)

Я также попробовал:

@AfterThrowing(value = "(execution(* *.*(..))) throws MySpecificException, throwing = "throwable")

но этого недостаточно, поскольку что, если метод объявляет, что он вызывает много исключений?

Любые предложения о том, как отлавливать только мои соответствующие исключения, не фильтруя их внутри реализации pointcut?

Спасибо

1 ответ

Решение

Ваш код не является исполняемым, пожалуйста, предоставьте MCVE или хотя бы полный аспект в следующий раз. Вы даже не предоставляете подпись совета. Это не хороший способ задавать вопросы о SO. Как пользователь с 1000+ очками репутации, вы должны это знать.

Во всяком случае, ответ на ваш вопрос на самом деле очень прост. Предполагая, что у вас есть этот пример кода:

Класс исключения + приложение драйвера:

package de.scrum_master.app;

public class MySpecificException extends Exception {
  private static final long serialVersionUID = 1L;
}
package de.scrum_master.app;

import java.io.IOException;

public class Application {
  public String doSomething(Integer number) {
    return number.toString();
  }

  public void doSomethingElse(boolean doThrow) throws MySpecificException {
    if (doThrow)
      throw new MySpecificException();
  }

  public void doWhatever(boolean doThrow) throws MySpecificException, IOException {
    if (doThrow)
      throw new MySpecificException();
    else
      throw new IOException();
  }

  public static void main(String[] args) throws MySpecificException, IOException {
    Application application = new Application();

    // Just so as not to mess up the console output in the IDE for this demo
    System.setErr(System.out);

    // No exceptions here
    application.doSomething(11);
    application.doSomethingElse(false);

    // Let's catch some exceptions
    try {
      application.doSomethingElse(true);
    } catch (MySpecificException e) {
      System.out.println("Caught " + e);
    }
    try {
      application.doWhatever(true);
    } catch (MySpecificException e) {
      System.out.println("Caught " + e);
    }
    try {
      application.doWhatever(false);
    } catch (IOException e) {
      System.out.println("Caught " + e);
    }

    // Do not catch this one
    application.doSomethingElse(true);
  }
}

Консольный журнал без аспекта:

Caught de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
Caught java.io.IOException
Exception in thread "main" de.scrum_master.app.MySpecificException
    at de.scrum_master.app.Application.doSomethingElse(Application.java:12)
    at de.scrum_master.app.Application.main(Application.java:50)

Здесь нет сюрпризов. Мы поймали и выловили исключения разных типов. Теперь мы хотим, чтобы аспект регистрировал все случаи MySpecificExceptionнезависимо от того, поймали они или нет.

аспект:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;

import de.scrum_master.app.MySpecificException;

@Aspect
public class ExceptionLogger {
  @AfterThrowing(value = "(execution(* *.*(..)))", throwing = "mySpecificException")
  public void logException(JoinPoint thisJoinPoint, MySpecificException mySpecificException) {
    System.out.println(thisJoinPoint + " -> " + mySpecificException);
  }
}

Видите подпись метода совета? Просто ограничьте параметр исключения желаемым типом.

Консольный журнал с аспектом:

execution(void de.scrum_master.app.Application.doSomethingElse(boolean)) -> de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
execution(void de.scrum_master.app.Application.doWhatever(boolean)) -> de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
Caught java.io.IOException
execution(void de.scrum_master.app.Application.doSomethingElse(boolean)) -> de.scrum_master.app.MySpecificException
execution(void de.scrum_master.app.Application.main(String[])) -> de.scrum_master.app.MySpecificException
Exception in thread "main" de.scrum_master.app.MySpecificException
    at de.scrum_master.app.Application.doSomethingElse(Application.java:12)
    at de.scrum_master.app.Application.main(Application.java:50)
Другие вопросы по тегам