Spring AOP。如何为带注释的 class 中的所有 public 方法创建切入点
Spring AOP. How to make pointcut for all public methods in annotated class
我需要处理从 class 的 public 方法抛出的所有异常,这些方法用一些注释进行了注释。
我尝试使用 Spring AOP。这是我的记录器:
@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
是我的注解。
然后我在我的配置中添加了 @EnableAspectJAutoProxy
注释 class。
首先,我尝试注释一些抛出异常的方法。它工作正常,但我如何才能使 class 中的所有 public 方法都使用 @Loggable
注释?
您可以像这样创建方面,其中 @LogMe
是注释:
@Pointcut("execution(@LogMe * *(..))")
以匹配所有 public 方法。
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());
}
}
用 @Aspect
注释的 class 不是 @Component
,因此如果您启用了组件扫描,它就不会被拾取。如果您的上下文中没有方面,则 AOP 没有任何用处。
要解决此问题,您可以执行以下 3 项操作中的一项:
- 将
@Component
放在 @Aspect
旁边
- 将
@Aspect
定义为 @Bean
- 添加额外的`@ComponentScan(includeFilter={@Filter(org.aspectj.lang.annotation.Aspect)}
显然选项 #1 是最容易做到的。
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?
你需要写一个与之匹配的切点。像下面这样的东西应该可以解决问题。
@Pointcut("public * ((@Loggable *)+).*(..)) && within(@Loggable *)")
连同
@Pointcut("@Loggable * *(..)")
这将命中带注释的方法或带注释的 class 中的 public 方法。这受到来自 Spring 框架 AnnotationTransactionAspect
的代码的启发。
我需要处理从 class 的 public 方法抛出的所有异常,这些方法用一些注释进行了注释。 我尝试使用 Spring AOP。这是我的记录器:
@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
是我的注解。
然后我在我的配置中添加了 @EnableAspectJAutoProxy
注释 class。
首先,我尝试注释一些抛出异常的方法。它工作正常,但我如何才能使 class 中的所有 public 方法都使用 @Loggable
注释?
您可以像这样创建方面,其中 @LogMe
是注释:
@Pointcut("execution(@LogMe * *(..))")
以匹配所有 public 方法。
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());
}
}
用 @Aspect
注释的 class 不是 @Component
,因此如果您启用了组件扫描,它就不会被拾取。如果您的上下文中没有方面,则 AOP 没有任何用处。
要解决此问题,您可以执行以下 3 项操作中的一项:
- 将
@Component
放在@Aspect
旁边 - 将
@Aspect
定义为@Bean
- 添加额外的`@ComponentScan(includeFilter={@Filter(org.aspectj.lang.annotation.Aspect)}
显然选项 #1 是最容易做到的。
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?
你需要写一个与之匹配的切点。像下面这样的东西应该可以解决问题。
@Pointcut("public * ((@Loggable *)+).*(..)) && within(@Loggable *)")
连同
@Pointcut("@Loggable * *(..)")
这将命中带注释的方法或带注释的 class 中的 public 方法。这受到来自 Spring 框架 AnnotationTransactionAspect
的代码的启发。