簡體   English   中英

如何在java中為許多方法添加類似的功能?

[英]How can I add similar functionality to a number of methods in java?

我有很多日志記錄方法,比如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個記錄方法?

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

如果這聽起來太深奧,那么更簡單,實際的解決方案是在單獨的方法中添加睡眠,然后在每個記錄方法中調用該方法。 第一次執行此操作時,需要觸摸每個方法,但下次如果要修改額外行為或添加其他內容,則可以在一個位置執行此操作。

看起來您想要使用面向方面編程。 您可以將Spring用於AOP或AspectJ。

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

創建一個具有靜態SleepFor方法的實用程序類,該方法包含try ... catch塊並從您希望睡眠的每個方法中調用它?

替換所有System.out.println(msg(SOME_ACTION)); with printAndWait(SOME_ACTION); 你應該能夠通過查找和替換來做到這一點。 然后創建一個方法

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

這樣代碼就會顯示一次,您可以在一個地方輕松更改它。

替換所有的logSomeAction()與一個單一的方法logAction(Action a)方法。 這樣,當您將來添加更多操作時,您將不會重復代碼來處理操作日志和線程休眠。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM