2017-03-24 3 views
0

Je dois gérer toutes les exceptions qui sont levées à partir de méthodes publiques de classe annotées avec des annotations. J'essaie d'utiliser Spring AOP. Ceci est mon enregistreur:AOP de printemps. Comment faire pointcut pour toutes les méthodes publiques dans la classe annotée

@Aspect 
public class Logger { 
    private final Logger log = LoggerFactory.getLogger(this.getClass()); 

    @Pointcut("@annotation(loggable)") 
    public void isLoggable(Loggable loggable) { 
    } 

    @AfterThrowing(pointcut = "isLoggable(loggable)", throwing = "e") 
    public void afterThrowing(Loggable loggable, Exception e) throws Throwable { 
     log.error("AFTER", e); 
    } 

@Loggable est mon annotation. J'ai ajouté @EnableAspectJAutoProxy à ma classe de configuration.

D'abord, j'ai essayé d'annoter une méthode de méthode qui déclenche une exception. Cela fonctionne bien mais comment puis-je faire fonctionner ce travail pour toutes les méthodes publiques en classe annotées avec @Loggable annotation?

+2

Est-ce que votre 'Logger' est un' @ Bean' ... Un '@ Aspect' n'est pas un' @ Component' et en tant que tel, les composants ne seront pas analysés. SO soit l'enregistrer en tant que bean ou ajouter '@ Component' pour le détecter ou créer un' @ ComponentScan' pour balayer tous les beans annotés avec '@ Aspect'. De toute façon, votre aspect doit devenir un haricot, sinon il n'existe pas et rien ne se passera. –

+1

Votre solution avec des conseils @around est correcte. Essayez de déboguer, vérifiez chaque fois que le conseil est exécuté. –

+0

@ M.Deinum Merci! C'était une erreur très stupide. – Kirill

Répondre

3

Vous pouvez créer l'aspect comme ceci, où logMe est l'annotation. @Pointcut ("exécution (@LogMe * * (..))") pour répondre à toutes les méthodes publiques

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Pointcut; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.stereotype.Component; 
import org.springframework.util.StopWatch; 


@Aspect 
@Component 
public class LogExecutionTime { 
    private static final String LOG_MESSAGE_FORMAT = "%s.%s execution time: %dms"; 
    private static final Logger logger = LoggerFactory.getLogger(LogExecutionTime.class); 

@Pointcut("execution(@LogMe * *(..))") 
public void isAnnotated() {} 

@Around("isAnnotated()") 
/** 
* method will add log statement of running time of the methods which are annotated with @LogMe 
* @param joinPoint 
* @return 
* @throws Throwable 
*/ 
public Object logTimeMethod(ProceedingJoinPoint joinPoint) throws Throwable { 
StopWatch stopWatch = new StopWatch(); 
stopWatch.start(); 

Object retVal = joinPoint.proceed(); 

stopWatch.stop(); 

logExecutionTime(joinPoint, stopWatch); 
return retVal; 
} 

    private void logExecutionTime(ProceedingJoinPoint joinPoint, StopWatch stopWatch) { 
    String logMessage = String.format(LOG_MESSAGE_FORMAT, joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName(), stopWatch.getTotalTimeMillis()); 
logger.info(logMessage.toString()); 
} 
} 
1

Une classe annotée avec @Aspect n'est pas un @Component donc si vous avez la numérisation composante permis a gagné ne sera pas ramassé. S'il n'y a pas d'Aspect dans votre contexte, il n'y a rien à utiliser pour AOP.

Pour résoudre ce problème, vous pouvez faire 1 de 3 choses:

  1. Mettez @Component à côté du @Aspect
  2. Définir le @Aspect comme @Bean
  3. Ajouter un montant supplémentaire `@ComponentScan (includeFilter = {@ filtre (org.aspectj.lang.annotation.Aspect)}

Il est évident que l'option 1 est le plus facile à faire.

D'abord, j'ai essayé d'annoter une méthode de méthode qui déclenche une exception. Cela fonctionne bien mais comment puis-je faire en sorte que cela fonctionne pour toutes les méthodes publiques en classe annotées avec l'annotation @Loggable?

Vous devez écrire une coupe de point correspondant à cela. Quelque chose comme ce qui suit devrait faire l'affaire.

@Pointcut("public * ((@Loggable *)+).*(..)) && within(@Loggable *)") 

avec

@Pointcut("@Loggable * *(..)") 

qui frappera les méthodes annotées ou les méthodes publiques dans les classes annotées. Ceci est inspiré par le code du AnnotationTransactionAspect du Spring Framework.