3

我有很多用于记录的方法,例如logSomeActionlogAnotherAction

现在我希望所有这些方法在打印消息(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

您可以使用Aspects为您的方法添加额外的“正交”功能。

如果这听起来太深奥,一个更简单、更实际的解决方案是在单独的方法中添加睡眠,然后在每个日志记录方法中调用该方法。第一次执行此操作时,您需要触摸每个方法,但下次如果您想修改额外的行为或添加其他内容,您可以在一个地方执行此操作。

于 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));
   }
}

然后,您可以让 Java 代理包装SomeActionLogger接口

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

logSomeAction()用一个方法替换所有logAction(Action a)方法。这样,当您将来添加更多操作时,您将不会重复处理操作日志和线程睡眠的代码。

于 2010-06-12T13:34:52.510 回答
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();
   } 
} 

这样代码会出现一次,您可以在一个地方轻松更改它。

于 2010-06-12T11:49:34.787 回答