2012-04-27 15 views
5

Tengo algunos métodos que arrojan alguna excepción, y quiero usar AspectJ alrededor de asesorar para calcular el tiempo de ejecución y si se lanza alguna excepción e iniciar sesión en el registro de errores y continuar el fluya volviendo a lanzar la excepción.Cómo volver a lanzar la excepción en AspectJ alrededor del consejo

Intenté lograr esto siguiendo pero eclipse dice "Tipo de excepción no controlada".

Código-contra quien aspectj es utilizado: -

public interface Iface { 
    public void reload() throws TException; 

    public TUser getUserFromUserId(int userId, String serverId) throws ResumeNotFoundException, TException; 

    public TUser getUserFromUsername(String username, String serverId) throws ResumeNotFoundException, TException; 

    public TResume getPartialActiveProfileFromUserId(int userId, int sectionsBitField, String serverId) throws ResumeNotFoundException, UserNotFoundException; 

    public TResume getPartialActiveProfileFromUsername(String username, int sectionsBitField, String serverId) throws ResumeNotFoundException, UserNotFoundException, TException; 
} 

Código aspectj: -

public aspect AspectServerLog { 

public static final Logger ERR_LOG = LoggerFactory.getLogger("error"); 

Object around() : call (* com.abc.Iface.* (..)) { 
    Object ret; 
    Throwable ex = null; 

    StopWatch watch = new Slf4JStopWatch(); 

    try { 
    ret = proceed(); 
    }catch (UserNotFoundException e) { 
    ex = e ; 
    throw e ; 
    } catch (ResumeNotFoundException e) { 
    ex = e ; 
    throw e ; 
    } catch (Throwable e) { 
    ex = e ; 
    throw new RuntimeException(e); 
    }finally{ 

    watch.stop(thisJoinPoint.toShortString()); 

    if(ex!=null){ 
     StringBuilder mesg = new StringBuilder("Exception in "); 
     mesg.append(thisJoinPoint.toShortString()).append('('); 
     for(Object o : thisJoinPoint.getArgs()) { 
     mesg.append(o).append(','); 
     } 
     mesg.append(')'); 

     ERR_LOG.error(mesg.toString(), ex); 
     numEx++; 
    } 

    } 
return ret; 
} 
} 

Por favor, ayuda por qué este AspectJ no está funcionando.

Respuesta

10

puede evitar las excepciones y simplemente utilizar un bloque try/finally sin la trampa. Y si realmente se necesita para registrar la excepción puede utilizar una después de lanzar el asesoramiento, así:

public aspect AspectServerLog { 

    public static final Logger ERR_LOG = LoggerFactory.getLogger("error"); 

    Object around() : call (* com.abc.Iface.* (..)) { 

     StopWatch watch = new Slf4JStopWatch(); 

     try { 
      return proceed(); 
     } finally { 
      watch.stop(thisJoinPoint.toShortString()); 
     } 
    } 

    after() throwing (Exception ex) : call (* com.abc.Iface.* (..)) { 
     StringBuilder mesg = new StringBuilder("Exception in "); 
     mesg.append(thisJoinPoint.toShortString()).append('('); 
     for (Object o : thisJoinPoint.getArgs()) { 
      mesg.append(o).append(','); 
     } 
     mesg.append(')'); 

     ERR_LOG.error(mesg.toString(), ex); 
    } 

} 
+0

gracias, esta es una gran solución simple. –

6

Me temo que no puede escribir consejos para arrojar excepciones que no están declaradas para ser lanzadas en el punto de unión coincidente. Por: http://www.eclipse.org/aspectj/doc/released/progguide/semantics-advice.html: "Una declaración de consejo debe incluir una cláusula throws que enumere las excepciones verificadas que el cuerpo puede arrojar. Esta lista de excepciones comprobadas debe ser compatible con cada punto de unión objetivo del consejo, o el compilador indica un error".

Se ha discutido en la lista de correo aspectj trata de mejorar esta situación - ver las discusiones de esta manera: http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg01412.html

pero básicamente lo que necesita hacer es un consejo diferente para cada variante de la declaración de excepción. Por ejemplo:

Object around() throws ResumeServiceException, ResumeNotFoundException, TException: 
    call (* Iface.* (..) throws ResumeServiceException, ResumeNotFoundException, TException) { 

que aconsejarán en todas partes que tenga esas 3 excepciones.

1

Hay una solución alternativa "feo" - Las encontré en Spring4 AbstractTransactionAspect

Object around(...): ... { 
    try { 
     return proceed(...); 
    } 
    catch (RuntimeException ex) { 
     throw ex; 
    } 
    catch (Error err) { 
     throw err; 
    } 
    catch (Throwable thr) { 
     Rethrower.rethrow(thr); 
     throw new IllegalStateException("Should never get here", thr); 
    } 
} 

/** 
* Ugly but safe workaround: We need to be able to propagate checked exceptions, 
* despite AspectJ around advice supporting specifically declared exceptions only. 
*/ 
private static class Rethrower { 

    public static void rethrow(final Throwable exception) { 
     class CheckedExceptionRethrower<T extends Throwable> { 
      @SuppressWarnings("unchecked") 
      private void rethrow(Throwable exception) throws T { 
       throw (T) exception; 
      } 
     } 
     new CheckedExceptionRethrower<RuntimeException>().rethrow(exception); 
    } 
} 
Cuestiones relacionadas