I need to handle all the exceptions that are thrown from public methods of class annotated with some annotation. I trying to use Spring AOP. This is my logger:
@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
is my annotation.
Then I've added @EnableAspectJAutoProxy
annotation to my configuration class.
First I've tried to annotate some method that throws an exception. It works fine but how can I make this work for all public methods in class annotated with @Loggable
annotation?
You can create the aspect like this, where @LogMe
is the annotation: @Pointcut("execution(@LogMe * *(..))")
to match all the public methods.
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() {}
/**
* Method will add log statement of running time of the methods which are annotated with @LogMe
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("isAnnotated()")
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());
}
}
A class annotated with @Aspect
isn't a @Component
so if you have component scanning enabled it won't be picked up. If there is no Aspect in your context, there is nothing use for AOP.
To fix this you can do 1 of 3 things:
@Component
next to the @Aspect
@Aspect
as a @Bean
Obviously option #1 is the easiest to do.
First I've tried to annotate some method method that throws an exception. It works fine but how can I make this work for all public methods in class annotated with @Loggable annotation?
You need to write a point cut that matches that. Something like the following should do the trick.
@Pointcut("public * ((@Loggable *)+).*(..)) && within(@Loggable *)")
together with
@Pointcut("@Loggable * *(..)")
Which will hit for annotated methods or public methods in annotated classes. This is inspired by the code from the AnnotationTransactionAspect
from the Spring Framework.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.