Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何向java中的许多方法添加类似的功能?_Java_Language Features_Proxy Classes - Fatal编程技术网

如何向java中的许多方法添加类似的功能?

如何向java中的许多方法添加类似的功能?,java,language-features,proxy-classes,Java,Language Features,Proxy Classes,我有很多方法来记录日志,比如logSomeAction,logAnotherAction等等 现在,我希望所有这些方法在打印消息(Thread.sleep)后进行一个小暂停 如果我手动执行,我会执行以下操作: //before: public static void logSomeAction () { System.out.println (msg(SOME_ACTION)); } //after: public static void logSomeAction () { Sy

我有很多方法来记录日志,比如
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) { }
}
public interface SomeActionLogger
{
   void logSomeAction();
   void logSomeOtherAction();
   // etc..
}
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));
}
我记得Java有代理类和其他一些神奇的工具。有没有办法避免将n个睡眠块复制粘贴到n个日志记录方法

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


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

创建一个实用程序类,该类具有静态
SleepFor
方法,其中包括您的
try。。。捕捉
块并从每个需要睡眠的方法调用它?

看起来您想要使用面向方面的编程。您可以将Spring用于AOP或AspectJ。

替换所有System.out.println(msg(SOME_ACTION));使用print和wait(一些动作); 您应该能够使用“查找并替换”来完成此操作。 然后创建一个方法

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)
方法。这样,将来添加更多操作时,就不会重复处理操作日志和线程睡眠的代码。

OP在评论中提到首选解决方案是使用普通java代理。当前的代码是作为静态方法实现的——为了使java代理具有任何用途,logger类需要作为接口进行修改。大概是这样的:

//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) { }
}
public interface SomeActionLogger
{
   void logSomeAction();
   void logSomeOtherAction();
   // etc..
}
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));
}
然后创建具体的实现

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
与日志接口正交-它可用于向任何接口添加延迟。然后,您可以创建一个通用包装方法,如下所示:

//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) { }
}
public interface SomeActionLogger
{
   void logSomeAction();
   void logSomeOtherAction();
   // etc..
}
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));
}
public T addDelay(T委托、int延迟、类接口类型)
{
return(T)Proxy.newProxyInstance(
delegate.getClass().getClassLoader(),
新类[]{type},
新的DelayAfterInvocationHandler(委托,延迟));
}

虽然我不喜欢方面,但这正是它们的用途。注意,您需要使用单独的编译器,因为方面不是标准Java实现的一部分;是JavaI的一个常见概念。我喜欢方面的概念,我甚至在春季学到了一些关于方面的知识。但是我自己还没有足够的知识来解决这个问题,但是我需要完成这个任务。您是否有适当的代码或至少sscce?哪些依赖项应该被解决?Aspect有一个缺点,就是你在编辑器中看到的代码不一定是正在运行的代码。不,我没有。我想使用普通的旧代理,但我不记得语法,我从来没有足够的经验使用它们。顺便说一句,AOP也在幕后使用代理(可能是其他一些代理实现,但想法是一样的)