如何使用AOP和AspectJ进行日志记录?

Mic*_*ael 27 java logging aop aspectj

我想在我的所有公共方法中添加"trace"消息,如下所示:

public void foo(s:String, n:int) { // log is a log4j logger or any other library
  log.trace(String.format("Enter foo with s: %s, n: %d", s, n))
  ...
  log.trace("Exit foo") 
}

现在我想log.trace用AOP(和字节码检测)自动将所有这些添加到我的方法中.我在考虑AspectJ.是否有意义?你知道任何开放源代码吗?

Ped*_*rdi 28

我创建了一个简单的方面来捕获公共方法的执行.这个AspectJ代码的核心是切入点定义:

pointcut publicMethodExecuted(): execution(public * *(..));
Run Code Online (Sandbox Code Playgroud)

这里我们使用任意数量的参数在任何包和任何类上捕获具有任何返回类型的所有公共方法.

建议执行可以在下面的代码片段中可视化:

after(): publicMethodExecuted() {
    System.out.printf("Enters on method: %s. \n", thisJoinPoint.getSignature());

    Object[] arguments = thisJoinPoint.getArgs();
    for (int i =0; i < arguments.length; i++){
        Object argument = arguments[i];
        if (argument != null){
            System.out.printf("With argument of type %s and value %s. \n", argument.getClass().toString(), argument);
        }
    }

    System.out.printf("Exits method: %s. \n", thisJoinPoint.getSignature());
}
Run Code Online (Sandbox Code Playgroud)

此建议使用thisJoinPoint来获取方法签名和参数.就是这样.这是方面代码:

public aspect LogAspect {

pointcut publicMethodExecuted(): execution(public * *(..));

after(): publicMethodExecuted() {
    System.out.printf("Enters on method: %s. \n", thisJoinPoint.getSignature());

    Object[] arguments = thisJoinPoint.getArgs();
    for (int i =0; i < arguments.length; i++){
        Object argument = arguments[i];
        if (argument != null){
            System.out.printf("With argument of type %s and value %s. \n", argument.getClass().toString(), argument);
        }
    }
    System.out.printf("Exits method: %s. \n", thisJoinPoint.getSignature());
}
Run Code Online (Sandbox Code Playgroud)

对于更复杂的例子,我会推荐AspectJ:In Action.

  • 要注意`System.out`,你真的应该使用一个日志框架外观,如SLF4J (3认同)

yeg*_*256 26

@Loggable来自jcabi-aspects的注释和AspectJ 方面是一个现成的机制(我是开发人员):

@Loggable(Loggable.DEBUG)
public String load(URL url) {
  return url.openConnection().getContent();
}
Run Code Online (Sandbox Code Playgroud)

要根据问题的要求记录进入和退出:

@Loggable(Loggable.DEBUG, prepend=true)
public String load(URL url) {
  return url.openConnection().getContent();
}
Run Code Online (Sandbox Code Playgroud)

所有日志都转到SLF4J.查看此帖子了解更多详情.