如何用log4j自动记录类中调用的每个方法?[英] How can i log every method called in a class automatically with log4j

本文是小编为大家收集整理的关于如何用log4j自动记录类中调用的每个方法?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有一个带有数据库调用的类,我通常想使用log4j:

在此类中登录该类别的每个方法(使用参数)
logger.debug("foo(id="+id+") initiated");

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

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

推荐答案

尝试 @Loggable @Loggable 注释和< jcabi aspects (我是开发人员):

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

所有方法调用均通过SLF4J记录.

本博客文章逐步解释了它:使用AOP和注释记录Java方法

其他推荐答案

如果您的接口声明要登录的方法,则可以使用标准代理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;
    }
  }

其他推荐答案

一种可能的解决方案是使用aptivej.想法是将方面附加到您希望登录的每个方法,并且执行记录是方面而不是方法. LeactJ记录的一个示例是在Stackoverflow ./p>

本文地址:https://www.itbaoku.cn/post/1574857.html

问题描述

I have a class with database calls, and I generally want to log every method called (with arguments) in this class with log4j:

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

Is it possible to do this automatically? Maybe by using some sort of annotation in start of each method instead of writing every single logger.debug?

Today I have to update my logging.debug every time I change arguments or method name.

推荐答案

Try @Loggable annotation and an AspectJ aspect from jcabi-aspects (I'm a developer):

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

All method calls are logged through SLF4J.

This blog post explains it step by step: Java Method Logging with AOP and Annotations

其他推荐答案

If you have interfaces declaring the methods you want to log calls to, you can use the standard Proxy API to achieve what you want.

The Proxy API would allow you to wrap your actual implementation in a new, proxy class, that would log the call, and the forward the call to implementation. You just have to implement one InvocationHandler that does the logging and the forwarding.

For example,

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
  }
}

You can also easily log the return values and exceptions thrown by the methods, just by changing the code in the InvocationHandler. Also, you could use any logging framework you like instead of System.out.println as in the example.

To log return values and exceptions, you could do something like:

  @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;
    }
  }

其他推荐答案

One possible solution would be to use aspectj. Idea would be to attach aspect to every method you wish to log, and perform logging is aspect instead of a method. One example of aspectj logging is right here in stackoverflow.