0

我需要处理从带有一些注释的类的公共方法抛出的所有异常。我尝试使用 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我的配置类中添加了注释。

首先,我尝试注释一些引发异常的方法。它工作得很好,但我怎样才能使这个工作对类中用注释进行@Loggable注释的所有公共方法起作用?

4

2 回答 2

4

您可以像这样创建方面,@LogMe注解在哪里: @Pointcut("execution(@LogMe * *(..))")以匹配所有公共方法。

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());
    }
}
于 2017-03-24T10:04:39.773 回答
2

带有注释的类@Aspect不是,@Component因此如果您启用了组件扫描,它将不会被拾取。如果您的上下文中没有 Aspect,则 AOP 没有任何用处。

要解决此问题,您可以做 3 件事中的 1 件事:

  1. 放在@Component旁边@Aspect
  2. 定义@Aspect@Bean
  3. 添加一个额外的`@ComponentScan(includeFilter={@Filter(org.aspectj.lang.annotation.Aspect)}

显然选项#1是最容易做到的。

首先,我尝试注释一些引发异常的方法。它工作正常,但我怎样才能使这个工作适用于类中使用@Loggable 注释注释的所有公共方法?

您需要编写一个与之匹配的切入点。像下面这样的东西应该可以解决问题。

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

和...一起

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

这将在带注释的类中针对带注释的方法或公共方法。这是受AnnotationTransactionAspectSpring Framework 中代码的启发。

于 2017-03-24T10:29:37.453 回答