3

などlogSomeAction、ログを記録するための方法がたくさんあります。logAnotherAction

ここで、これらすべてのメソッドがメッセージ (Thread.sleep) を出力した後に少し一時停止するようにします。

手動で行う場合は、次のようにします。

//before:
public static void logSomeAction () {
   System.out.println (msg(SOME_ACTION));
}

//after:
public static void logSomeAction () {
   System.out.println (msg(SOME_ACTION));
   try {
      Thread.sleep (2000);
   } catch (InterruptedException ignored) { }
}

Javaにはプロキシクラスやその他の魔法のツールがあることを覚えています。N個のスリープブロックをN個のロギングメソッドにコピーアンドペーストするのを避ける方法はありますか?

4

6 に答える 6

7

アスペクトを使用して、追加の「直交」機能をメソッドに追加できます。

それが難解すぎるように聞こえる場合は、別のメソッドにスリープを追加し、各ロギング メソッドでそのメソッドを呼び出すという、より単純で現実的な解決策があります。初めてこれを行うときは、各メソッドに触れる必要がありますが、次回余分な動作を変更したり、何か他のものを追加したりする場合は、1 か所で行うことができます。

于 2010-06-12T11:35:55.417 に答える
2

アスペクト指向プログラミングを使用したいようです。Spring を AOP または AspectJ に使用できます。

于 2010-06-12T11:36:43.627 に答える
1

OPはコメントで、好ましい解決策はプレーンなJavaプロキシを使用することであると述べています。現在のコードは静的メソッドとして実装されています。Java プロキシを使用するには、ロガー クラスをインターフェイスとして作り直す必要があります。このようなもの:

public interface SomeActionLogger
{
   void logSomeAction();
   void logSomeOtherAction();
   // etc..
}

次に、具体的な実装を作成します

public class SystemOutActionLogger implements SomeActionLogger
{
   public void logSomeAction () {
      System.out.println (msg(SOME_ACTION));
   }
}

SomeActionLoggerその後、Java プロキシにインターフェイスをラップさせることができます

class DelayAfterInvocationHandler implements InvocationHandler
{
    private Object delegate;
    private int duration;

    DelayAfterInvocationHandler(Object delegate, int duration)
    {
        this.delegate = delegate;
        this.duration = duration;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        Object returnValue = method.invoke(delegate, args);
        Thread.sleep(duration);
        // you may want to catch InterruptedEception
        return returnValue;
    }
}

あまりきれいではないプロキシ コードの一部を非表示にするために、ロガーをラップして遅延を作成するメソッドを使用できます。

public ActionLogger addDelay(SomeActionLogger logger, int delay)
{
    return (ActionLogger)Proxy.newProxyInstance(
       impl.getClass().getClassLoader(),
       new Class[] { SomeActionLogger.class }, 
       new DelayAfterInvocationHandler(logger, delay));
}

だからあなたはそれから書く

SomeActionLogger log = addDelay(new SystemOutActionLogger(), 2000);

はロギング インターフェイスと直交していることに注意してくださいDelayInvocationHandler。任意のインターフェイスに遅延を追加するために使用できます。次に、次のような一般的なラッピング メソッドを作成できます。

public <T> T addDelay(T delegate, int delay, Class<T> interfaceType)
{
    return (T)Proxy.newProxyInstance(
       delegate.getClass().getClassLoader(),
       new Class[] { type }, 
       new DelayAfterInvocationHandler(delegate, delay));
}
于 2010-06-12T15:48:31.760 に答える
0

SleepForブロックを含む静的メソッドを持つユーティリティ クラスを作成しtry ... catch、スリープ状態にするすべてのメソッドからそれを呼び出しますか?

于 2010-06-12T11:36:23.013 に答える
0

System.out.println(msg(SOME_ACTION)); をすべて置き換えます。printAndWait(SOME_ACTION); で 検索と置換でそれを行うことができるはずです。次に、メソッドを作成します

public static void printAndWait(Object someAction) {
   System.out.println (msg(someAction)); 
   try { 
      Thread.sleep (2000); 
   } catch (InterruptedException ignored) {
      Thread.currentThread.interrupt();
   } 
} 

そうすれば、コードが一度表示され、1 か所で簡単に変更できます。

于 2010-06-12T11:49:34.787 に答える
0

logSomeAction()すべてのメソッドを 1 つのメソッドに置き換えますlogAction(Action a)。これにより、将来さらにアクションを追加するときに、アクション ログとスレッド スリープを処理するためにコードを繰り返す必要がなくなります。

于 2010-06-12T13:34:52.510 に答える