18

我有一个带有数据库调用的类,我通常想用 log4j 记录这个类中调用的每个方法(带参数):

logger.debug("foo(id="+id+") initiated");

是否可以自动执行此操作?也许通过在每个方法的开头使用某种注释而不是编写每个 logger.debug?

今天,每次更改参数或方法名称时,我都必须更新我的 logging.debug。

4

3 回答 3

12

尝试jcabi-aspects@Loggable的注释和 AspectJ方面(我是开发人员):

@Loggable(Loggable.INFO)
public String load(URL url) {
  return url.openConnection().getContent();
}

所有方法调用都通过 SLF4J 记录。

这篇博客文章逐步解释了它:Java Method Logging with AOP and Annotations

于 2013-02-03T08:19:52.327 回答
9

如果您有接口声明要记录调用的方法,则可以使用标准代理 API 来实现您想要的。

代理 API 将允许您将实际实现包装在一个新的代理类中,该类将记录调用并将调用转发到实现。您只需要实现一个执行InvocationHandler日志记录和转发的功能。

例如,

interface Calculator {
  int add(int a, int b);
}

class CalculatorImpl implements Calculator {
  @Override public int add(int a, int b) { return a+b; }
}

class LoggingInvocationHandler implements InvocationHandler {
  private final Object delegate;
  public LoggingInvocationHandler(final Object delegate) {
    this.delegate = delegate;
  }
  @Override invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("method: " + method + ", args: " + args);
    return method.invoke(delegate, args);
  }
}

class X {
  public static void main(String... args) {
    final Calculator calc = new CalculatorImpl();
    final Calculator loggingCalc =
      (Calculator) Proxy.newProxyInstance(X.class.getClassLoader(),
                                          new Class[] {Calculator.class},
                                          new LoggingInvocationHandler (calc));
    loggingCalc.add(2, 3); // shall print to the screen
  }
}

您还可以轻松记录方法抛出的返回值和异常,只需更改InvocationHandler. 此外,您可以使用任何您喜欢的日志框架,而不是System.out.println示例中的那样。

要记录返回值和异常,您可以执行以下操作:

  @Override invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("method: " + method + ", args: " + args);
    try {
      final Object ret = method.invoke(delegate, args);
      System.out.println("return: " + ret);
      return ret;
    } catch (Throwable t) {
      System.out.println("thrown: " + t);
      throw t;
    }
  }
于 2012-11-13T06:20:46.957 回答
5

一种可能的解决方案是使用 aspectj。想法是将方面附加到您希望记录的每个方法,并执行记录是方面而不是方法。aspectj 日志记录的一个示例就在 stackoverflow 中

于 2012-11-13T06:22:08.010 回答