2016-09-02 4 views
-2

2つのInvocationHandlerを作成します.1つはロギング用、もう1つは計測用です。それぞれは動作しますが、私はこれらの2つのチェーンをどのように作成するのかわからないので、両方が実行されます。私は両方InvocationHandlersが呼び出されるように、例えばLoggingInvocationHandlerがTimerInvocationHandler動的プロキシのチェーンを作成するには?

public class DynamicProxyMain { 

public static void main(String[] args) { 
    System.out.println("Starting dynamic proxy sample"); 

    SubjectInterface timerProxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader(), 
      new Class<?>[]{SubjectInterface.class}, 
      new TimerInvocationHandler(new SubjectInterfaceImpl())); 

    SubjectInterface logginProxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader(), 
      new Class<?>[]{SubjectInterface.class}, 
      new LoggingInvocationHandler(new SubjectInterfaceImpl())); 
    timerProxy.methodA("a"); 
    timerProxy.methodB("test b"); 
    timerProxy.methodC(1, "test c"); 

} 
} 

public class LoggingInvocationHandler implements InvocationHandler { 
Object impl; 
String CLASSNAME = this.getClass().getCanonicalName(); 

public LoggingInvocationHandler(Object impl){ 
    this.impl = impl; 

} 
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
    Object retVal; 
    System.out.println("LoggingHandler:" + this.getClass().getName() + " has been called"); 
    retVal = method.invoke(impl, args); 
    System.out.println("LoggingHandler:" + this.getClass().getName() + " has ended"); 
    return retVal; 

} 
} 


public class TimerInvocationHandler extends LoggingInvocationHandler   implements InvocationHandler{ 
private Object impl; 

public TimerInvocationHandler(Object impl) { 
    super(impl); 
    this.impl = impl; 
} 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 

    Object retVal = null; 
    System.out.println("getting duration time for method " + method.getName()); 
    long duration = -System.currentTimeMillis(); 
    retVal = super.invoke(proxy,method,args); 
    duration += System.currentTimeMillis(); 
    System.out.println("it took " + duration + " milliseconds"); 
    System.out.println("duration time handler has ended"); 
    return retVal; 
} 
} 

を拡張実は、私は、それを解決することを十分だろうと思いました。私は現在作業中のコードで自分の投稿を編集しました

+0

ハンドラの実装方法を教えてもらえますか? –

答えて

2

ログイン時間を測定するために限定されるものではなく、興味があり、詳細を知りたい場合は、linkをよく読んでください。

参加

  • InvocationChain - 呼び出しをディスパッチする責任があります。
  • Invocation - loggingtimerのようなものを入力する必要があります。
  • DynamicProxyHanlder - これは単に要求をInvocationChainに委任します。

実装における

DynamicProxyHandler.java

public class DynamicProxyHandler implements InvocationHandler { 
    private Object proxied; 
    InvocationChain chain = new InvocationChainImp(); 

    DynamicProxyHandler(Object proxied) { 
     this.proxied = proxied; 
    } 

    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     return chain.invoke(proxied, method, args); 
    } 

} 

Invocation.java

public interface Invocation { 
    Object invoke(Object callee, Method method, Object[] args, InvocationChain chain); 
} 

Invocat ionChain.java

public interface InvocationChain { 
    public Object invoke(Object callee, Method method, Object[] args); 
} 

InvocationChainImp.java

public class InvocationChainImp implements InvocationChain { 
    List<Invocation> list = new ArrayList<>(); 
    Object result; 
    Iterator<Invocation> tasks; 

    InvocationChainImp() { 
     list.add(new LoggingInvocation()); 
     list.add(new TimerInvocation()); 
     list.add(new FinalInvocation()); 
     tasks = list.iterator(); 
    } 

    @Override 
    public Object invoke(Object callee, Method method, Object[] args) { 
     if (tasks.hasNext()) { 
      Object result = tasks.next().invoke(callee, method, args, this); 
      this.result = (this.result == null ? result : this.result); 
     } 
     return this.result; 
    } 

最終なく、少なくとも、我々はなど、ロギング用Invocationインターフェイスに限定しなければならないいくつかのカスタムクラス、タイマーを定義したい

LoggingInvocation。要求が最終的に、プロキシインスタンス上で呼び出されたJava

public class LoggingInvocation implements Invocation { 
    @Override 
    public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) { 
     chain.invoke(callee, method, args); 
     Logger.getLogger(this.getClass().getCanonicalName()).info(method.getName() + "() execution logged!"); 
     return null; 
    } 
} 

TimerInvocation.java

public class TimerInvocation implements Invocation { 
    @Override 
    public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) { 
     long start_time = System.nanoTime(); 
     chain.invoke(callee, method, args); 
     long end_time = System.nanoTime(); 

     System.out.println("Timer: excution took " + (end_time - start_time)/1e6 + "ms"); 

     return null; 
    } 
} 

FinalInvocation.java

public class FinalInvocation implements Invocation { 
    @Override 
    public Object invoke(Object callee, Method method, Object[] args, InvocationChain chain) { 
     try { 
      return method.invoke(callee, args); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } catch (IllegalArgumentException e) { 
      e.printStackTrace(); 
     } catch (InvocationTargetException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 
} 

その他のコードは、実装が機能することを証明するために使用されているため、簡単です。
あなた自身で書きたい場合は、今読まなくてもすることができます。

SubjectInterface.java

public interface SubjectInterface { 
    String hello(); 
} 

SubjectInterfaceImp.java

public class SubjectInterfaceImp implements SubjectInterface { 
    @Override 
    public String hello() { 
     System.out.println("in SubjectInterfaceImp: Greeting!"); 
     return "hello"; 
    } 
} 

Main.java

public class Main { 
    public static void main(String[] args) throws Exception { 
     SubjectInterface subject = (SubjectInterface) Proxy.newProxyInstance(
       SubjectInterface.class.getClassLoader(), 
       new Class[] { SubjectInterface.class }, new DynamicProxyHandler(new SubjectInterfaceImp())); 
     System.out.println("in Main: subject.hello() = " + subject.hello()); 
    } 
} 

OK、十分なコードがあります。それはショータイムです。voila

in SubjectInterfaceImp: Greeting! 
Timer: excution took 0.532198ms 
九月 02, 2016 12:37:36 下午 LoggingInvocation invoke 
信息: hello() execution logged! 
in Main: subject.hello() = hello 
+0

起動の順序は非常に重要です**例えば、 'TimerInvocation'が最初に呼び出された場合、サブクエント呼び出しに費やされる時間が含まれるため、結果が不正確になる可能性があります。 –

+0

あなたの広範囲の答えをお寄せいただきありがとうございます、私はあなたの指示で私の解決策をリファクタリングしようとしました。現在、私は2つの問題に取り組んでいます。まず、実際のメソッドは呼び出されず、最初の呼び出しが呼び出されたときにイテレータが最後の項目にあるので、チェーンは最初のラウンドのみを処理します。したがって、次のラウンドではhasNextは見つかりません。私はあなたがhttps://github.com/crojay78/PatternPlaygroundをチェックしたい場合、私はGithubへの試みを公開しました。 –

+0

私はいくつかの変更を加えました。私はプロキシされたオブジェクトをInvocationChainImplに注入しました。リストに呼び出しハンドラがないとすぐに、実際のメソッドが呼び出され、タスクは初期値に設定されます。興味があれば、githubプロジェクトをチェックして、自由に最適化してください:-) –

0

これは自然な実装方法ではありません.TimerInvocationHandlerはLoggingInvocationHandlerとは何の関係もありません。 のInvocationHandlerであり、他のInovovationHandler

https://en.wikipedia.org/wiki/Decorator_pattern

EDITラップデコレータ定義:1件のコメントので、サンプル実装を提供するために、私に尋ねる、一部以下の追加が、これは正確ではありませんDecoratorパターンですが、しかし、他の人が解決策を理解できると思います。この場合にはTimeInvocationHandlerはあなたの場合、私は」少しDynamicProxyHandlerで動作するために変更され、それの実装を、あげるアイデアはIntercepting Filterとの類似性を負担する

public class TimerInvocationHandler implements InvocationHandler 
{ 
    protected InvocationHandler invocationHandler; 

    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
    { 
    //do whatever you want 
    Object result = invocationHandler.invoke(proxy, method, args); 
    // do what ever you want 
    return result; 
    } 
} 
+0

これはコメントにすることができますか、それとも可能にするために編集する必要があります – emotionlessbananas

+0

@Asterisk Ninja - 何を話していますか – hunter

関連する問題