2012-06-08 19 views
16

Widzę, że Guice i Spring używają AOP Alliance pod maską do przechwytywania metod i próbowałem dowiedzieć się, jak sprawić, by AOP Alliance przechwyciło i poradziło sobie z pewnymi wyjątkami, więc nie muszę pisanie tego samego kodu w kółko w każdym bloku catch.AOP Exception Handling

Ale po zapoznaniu się grać, to nie wygląda AOP Alliance zapewnia jakikolwiek sposób do przechwytywania rzucane Throwable S w taki sposób, że handler/Interceptor można zrobić kilka rzeczy (log wyjątek, etc.) i następnie ustalić, czy jakiekolwiek dalsze propagowanie wyjątku lub po prostu odzyskać z powrotem do następnego wiersza po wierszu, który zwrócił wyjątek:

HerpDerp hd = null; 

if(hd == null) 
    throw new RuntimeException("Herpyl derp!"); 

Manny.pacquiao(); 

szukam mechanizmu obsługi wyjątków AOP, który przechwytywał RuntimeException i użyj logiki biznesowej, aby zdecydować, czy chcesz ją dalej propagować, czy też odzyskać po zadzwonieniu pod numer Manny.pacquioa() .

  • Jeśli jest to po prostu niemożliwe, aby to zrobić w Javie, proszę dać mi znać
  • Niezależnie od tego, czy jego możliwe, aby to zrobić w Javie, czy jest jakiś sposób aby przechwycić rzucony wyjątek z AOP Alliance lub czy muszę iść gdzie indziej. A jeśli muszę iść gdzieś indziej, gdzie? AspectJ?

Dzięki!

Odpowiedz

30

Możesz przechwytywać wyjątki za pomocą Spring AOP, ale nie wiem, czy to pasuje do twojego wymagania dla czystej struktury Java.

ze sprężyną, można napisać prosty AOP przechwytujących jako coś w rodzaju:

@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."); 
    } 
} 
} 

ale nie ma sposobu, aby powrócić do metody wywołującej lub kontynuować przetwarzanie na kolejnej linii. Jeśli jednak poradzisz sobie z tym wyjątkiem, nie będzie on bańką w łańcuchu, dopóki sam go nie zrzucisz.

1

Aby „złapać” przechwycone wyjątki z AspectJ, można użyć następującej proporcji:

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 
} 

Nie sądzę, że jest możliwe, aby „wrócić” do momentu wykonania.

+0

Thanks @Wim - jest oparte AOP obsługa wyjątków jak to nie jest możliwe w AOP Alliance? – IAmYourFaja

+0

Nie sądzę. Jeśli zaznaczysz [wiosenne dokumenty] (http://static.springsource.org/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/aop.html), pokaże to: 'Join point : punkt podczas wykonywania programu, taki jak wykonanie metody lub obsługa wyjątku. W Spring AOP, punkt sprzężenia zawsze reprezentuje wykonanie metody. " –

+0

Czy [ConstructorInterceptor] (http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/ConstructorInterceptor.html) w jakiś sposób może zostać zhakowany w celu przechwycenia wyjątków (jak są zbudowane)? – IAmYourFaja

3

Istnieje powód, dla którego to nie istnieje. Wymagałoby to przepisania struktury blokowej twojego kodu, tak jakbyś najpierw napisał blok try/catch. To, jak mi się wydaje, potencjalnie zagraża zmiennym zakresem i innymi rzeczami. Zadajesz pytanie AOP, aby przepisać kod bajtowy na coś podobnego do poniższego kodu, a to całkiem przeróbka.

HerpDerp hd = null; 

try { 
    if(hd == null) 
     throw new RuntimeException("Herpyl derp!"); 
} catch(RuntimeException e) { 
    if (someConditionIsMet) { 
     throw e; 
    } 
} 

Manny.pacquiao(); 
1

@ 4herpsand7derpsago Jeśli próbujesz zrobić, to złapać rzucony wyjątek przy użyciu AOP wykonywać różne zadania, aby ją obsłużyć, a następnie wraca do kodu, w którym wyjątek pierwotnie rzucone, myślę, że brakuje zrozumienia koncepcja AOP.

Jak podkreślić w kodzie

HerpDerp hd = null; 

if(hd == null) 
throw new RuntimeException("Herpyl derp!"); 

Manny.pacquiao(); 

Jeśli chcesz AOP złapać RuntimeException, należy wykonać kilka rzeczy z tym poradzić i wraca do Manny.pacquiao();, odpowiedź jest nie można. Powodem jest to, że kiedy RuntimeException jest rzucany i przechwytywany przez AOP, stos jest już pod twoim kodem AOP. nie możesz wrócić, aby wykonać Many.pacquiao();. Jedynym sposobem, jeśli chcesz kontynuować wykonywanie Many.pacquiao(); jest za pomocą try-finally bloku jak postępować

HerpDerp hd = null; 

try { 
    if(hd == null) 
     throw new RuntimeException("Herpyl derp!"); 
} finally { 
    Manny.pacquiao(); 
} 

Tylko wówczas Many.pacquiao() dostanie wykonany, ale zanim AOP złapać RuntimeException