2012-06-08 20 views
16

Veo que Guice y Spring usan la Alianza AOP bajo interceptación de métodos, y he estado tratando de encontrar la manera de lograr que AOP Alliance intercepte y maneje ciertas excepciones para que no tenga que mantener escribiendo el mismo código una y otra vez dentro de cada bloque catch.Manejo de excepciones AOP

Pero después de revisar la obra, que no se ve como AOP Alliance ofrece ninguna manera de interceptar lanzados Throwable s de tal manera que el controlador/interceptor puede hacer algunas cosas (log excepción, etc.) y luego determinar si o no para propagar la excepción más lejos o simplemente para recuperar de nuevo a la siguiente línea después de la línea que lanzó la excepción:

HerpDerp hd = null; 

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

Manny.pacquiao(); 

Busco un mecanismo de manejo de excepciones AOP que interceptar la RuntimeException y utilice la lógica comercial para decidir si seguir propagándola o recuperarse en la llamada Manny.pacquioa() .

  • Si simplemente no es posible hacer esto en Java, por favor hágamelo saber
  • Independientemente de si es o no su posible hacer esto en Java, hay una manera de interceptar excepción lanzada con AOP Alliance o ¿Tengo que ir a otro lugar? Y si tengo que ir a otro lugar, ¿dónde? ¿AspectJ?

Gracias!

Respuesta

30

Puede detectar excepciones con Spring AOP, pero no sé si eso concuerda con sus requisitos para un framework Java puro.

Con la primavera, puede escribir un simple interceptor AOP como algo parecido a:

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

pero no hay manera de volver al método de llamada o continuar el procesamiento en la línea subsiguiente. Sin embargo, si manejas la excepción aquí, no surgirá la cadena a menos que la vuelvas a lanzar tú mismo.

1

para "atrapar" excepciones no capturadas con AspectJ, puede utilizar el siguiente aspecto:

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 
} 

no creo que es posible "volver" al punto de ejecución.

+0

Gracias @Wim - está basado en AOP el manejo de excepciones como este no es posible con AOP Alliance? – IAmYourFaja

+0

No lo creo. Si marca [los documentos de primavera] (http://static.springsource.org/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/aop.html), se muestra esto: 'Punto de unión : un punto durante la ejecución de un programa, como la ejecución de un método o el manejo de una excepción. En Spring AOP, un punto de unión siempre representa una ejecución de método. –

+0

Podría [ConstructorInterceptor] (http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/ConstructorInterceptor.html) ser manipulado de alguna manera para interceptar excepciones. (como están construidos)? – IAmYourFaja

3

Hay una razón por la que esto no existe. Requeriría volver a escribir la estructura del bloque de su código como si hubiera escrito el bloque try/catch en primer lugar. Esto, me parece, potencialmente hace estragos con el alcance variable y otras cosas. Le está pidiendo a AOP que reescriba el código de bytes para que sea algo así como el siguiente código, y eso es bastante una reescritura.

HerpDerp hd = null; 

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

Manny.pacquiao(); 
1

@ 4herpsand7derpsago Si lo que estás tratando de hacer es coger la excepción lanzada usando AOP para llevar a cabo diversas tareas de manejar la situación y luego vuelve al código donde la excepción lanzada originalmente, creo que se olvida de entender el concepto de AOP.

Como usted señala en su código

HerpDerp hd = null; 

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

Manny.pacquiao(); 

Si desea AOP para tomar su RuntimeException, realice algunas cosas para manejarlo y vuelve a Manny.pacquiao();, la respuesta es que no se puede . La razón es porque cuando el AOP arroja RuntimeException, la pila ya está en su código AOP. no puede volver a ejecutar Many.pacquiao();. La única manera si desea continuar ejecutando Many.pacquiao(); es mediante el uso de bloques como try-finally siga

HerpDerp hd = null; 

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

Sólo entonces su Many.pacquiao() obtendrá ejecutado, pero antes de coger el AOP RuntimeException