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 を介してログに記録されます。

このブログ投稿では、手順を追って説明しています: AOP と注釈を使用した Java メソッドのログ記録

于 2013-02-03T08:19:52.327 に答える
9

呼び出しをログに記録するメソッドを宣言するインターフェースがある場合は、標準のProxyAPIを使用して目的を達成できます。

Proxy 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

考えられる解決策の 1 つは、aspectj を使用することです。アイデアは、ログに記録するすべてのメソッドにアスペクトをアタッチし、メソッドではなくアスペクトでログを実行することです。アスペクト ロギングの 1 つの例は、ここの stackoverflow にあります。

于 2012-11-13T06:22:08.010 に答える