ダイナミックプロキシは何ですか?
最初の静的プロキシの下で:
つまり、これは静的な薬で、プログラムは、コンパイルされたクラスが実行される前に、あります
ダイナミックエージェント:
これは、プログラムの実行前に、プロキシクラスが存在しない、ですが、プログラムは、動的なクラスが動的に生成されたプロキシクラスを実行しています。
次の考えがあるかもしれません
プロキシモードは何?何の技術?
プロキシモデルを使用するのはなぜ?メリットは何ですか?
ダイナミックプロキシシナリオは何?
私たちはそれを実装した動的プロキシについてお話しましょう:
Javaリフレクション技術を使用して主な動的プロキシ:
各エージェントクラスの説明は、一般的に存在するので、のInvocationHandlerに関するのにJavaAPIは、このインターフェイスのInvocationHandlerを実装する必要があり、ハンドルに各エージェントクラスに関連付けられます
場合は、プロキシクラスのメソッド呼び出しは、コールのInvocationHandler Invokeメソッドに移動します。
次のコードは、その牛のコードの参照です
ソースコードを見るのInvocationHandler、私はもはやそれを再度書きませんよ。
パブリックインターフェイスのInvocationHandler
{
パブリック抽象オブジェクトを呼び出し(オブジェクトobj、方法方法、[] AOBJオブジェクト)
Throwableをスローします。
}
このメソッドを呼び出し、いくつかのパラメータがあります。
OBJ:我々は呼び出すために実際のオブジェクトを表します
方法:当社メソッドの実際のオブジェクトを呼び出すためにあることを示しています。
AOBJ []:実際のオブジェクトメソッドの表現は、パラメータを受け付けます。
このインタフェースのInvocationHandlerこれを使用する方法、主にプロキシクラスを表示するには:
プロキシクラスのプロキシオブジェクトを作成することです
プロキシこのクラスは、これに方法があります:最も使用される方法であり、
パブリック静的オブジェクトnewProxyInstance(のClassLoaderクラスローダ、クラスAClassは[]、のInvocationHandler用のInvocationHandler)
IllegalArgumentExceptionがスローされます
パラメータ:
クラスローダー:クラスローダによってロードされたオブジェクトの定義
[] AClassは:プロキシ・オブジェクトはこれらのインタフェースを実装表すプロキシオブジェクトのためのインタフェースを提供することであり、
InvocationHandlerです:彼は、オブジェクトのInvocationHandlerにプロキシメソッド呼び出しを関連付けすることを
プロキシインタフェースのInvocationHandlerによって主動的プロキシクラス:
より良い理解を達成するために、特定の動的プロキシを見てください:
1.まず、間違いのインターフェイスが必要です。
パブリックインターフェースUserServiceの{
公共の文字列のgetName(int型のID);
公共の整数getAge(int型のID);
}
また、我々は、プロキシオブジェクトである、このインタフェースを実装する必要があります。
パブリッククラスUserServiceImplは{UserServiceのを実装します
@オーバーライド
パブリック文字列のgetName(int型のID){
System.out.println( "------のgetName ------");
「トム」を返します。
}
@オーバーライド
パブリック整数getAge(int型のID){
System.out.println( "------ getAge ------");
10を返します。
}
}
また、あなたは彼のinvokeメソッドを実現するために、のInvocationHandlerをカスタマイズする必要があります。
輸入java.lang.reflect.InvocationHandler。
輸入java.lang.reflect.Methodオブジェクト。
パブリッククラスMyInvocationHandlerは{のInvocationHandlerを実装します
プライベートオブジェクトのターゲット。
MyInvocationHandler(){
スーパー();
}
MyInvocationHandler(オブジェクト・ターゲット){
スーパー();
this.target =ターゲット。
}
@オーバーライド
パブリックオブジェクトを呼び出し(オブジェクトo、メソッドの方法は、[]引数オブジェクト)のThrowableを{スロー
IF( "のgetName" .equals(method.getName())){
System.out.println( "++++++の前に" + method.getName()+ "++++++");
オブジェクトの結果= method.invoke(ターゲット、引数)。
System.out.println( "++++++後に" + method.getName()+ "++++++");
結果を返します。
}他{
オブジェクトの結果= method.invoke(ターゲット、引数)。
結果を返します。
}
}
}
最後に、InvocationHandlerですだけでなく、プロキシはこのインタフェースを使用する方法を見て
輸入java.lang.reflect.InvocationHandler。
輸入java.lang.reflect.Proxyの;
パブリッククラスTestProxy {
パブリック静的無効メイン(文字列[] args){
UserServiceのUserServiceの=新しいUserServiceImpl();
InvocationHandlerのInvocationHandler =新しいMyInvocationHandler(UserServiceの);
UserServiceのuserServiceProxy =(UserServiceの)たとえば、Proxy.newProxyInstance(userService.getClass()のgetClassLoader()、
userService.getClass()でgetInterfaces()、のInvocationHandler)。
System.out.println(userServiceProxy.getName(1))。
System.out.println(userServiceProxy.getAge(1))。
}
}
newproxyInstanceがプロキシプロキシオブジェクトを生成するために使用される、UserServiceのは、特定の実装に向けられていると理解をより明確に見ることができます
UserServiceImpl
クラスメソッドは、実際のクラスに対応する、のInvocationHandlerインタフェースを実際のクラスローダを渡し、そして呼び出すNewproxyInstance方法を実現することができます。
System.out.println( "++++++の前に" + method.getName()+ "++++++");
実際には、このコード行は、上記の***特性を有し、かつ、時間AOP詳細に議論します。
これは、動的プロキシを達成するために、使用上の反射技術を見ることができ、我々はインターフェイスを定義する必要がありますが、時々は本当にインタフェースを定義したくない、だけで、クラスの良い定義を達成していくことができますし、あなたには、いくつかのコンテンツが可能追加実行した後、法の前に実行します。
これは、この良い使用と考えられるが、CGLIB CGLIB動的プロキシは非常に便利です。
ASMは、プロキシクラスのバイトコードを使用して生成するCGLIBバイトコード技術を使用しています。高い反射よりも効率が、エージェントが自己finalクラスではない、clglib要素は、プロキシクラスを統合しています。finalクラスは継承できません。
具体的な実現CGLIB次表情:
CGLIBのASMパッケージをダウンロードして、この2つのパッケージに依存する必要があなたのプロジェクトをパッケージ化:
まず、非finalクラスを必要とし、もはや反射のインタフェースを必要としません
パブリッククラスStudentService {
パブリック文字列のgetName(){
System.out.println( "------のgetName ------");
「トム」を返します。
}
公共の整数のgetId(){
System.out.println( "------ ------のgetId");
10を返します。
}
}
そして、クラス以上の機関が、あなたがインターセプタを定義する必要があるかを見てみましょう。
輸入net.sf.cglib.proxy.MethodInterceptor。
輸入net.sf.cglib.proxy.MethodProxy;
輸入java.lang.reflect.Methodオブジェクト。
パブリッククラスCglibProxyは{MethodInterceptorのを実装します
@オーバーライド
パブリックオブジェクトインターセプト(オブジェクトo、メソッドのメソッド、オブジェクト[]引数、
MethodProxy methodProxyは)のThrowableを{スロー
System.out.println( "++++++の前に" + methodProxy.getSuperName()
+ "++++++");
System.out.println(method.getName())。
オブジェクトO1 = methodProxy.invokeSuper(O、引数)。
System.out.println( "++++++の前に" + methodProxy.getSuperName()
+ "++++++");
O1を返します。
}
}
上記の方法に類似して呼び出す方法Interceptf本当にメソッドinvokeSuperを呼び出すためにinterceptfによってでのInvocationHandler:
最後に、このクラスのプロキシがそれをStudentService特にどのようCglbを見て:
輸入net.sf.cglib.proxy.Enhancer。
パブリッククラスTestCglib {
パブリック静的無効メイン(文字列[] args){
CglibProxy cglibProxy =新しいCglibProxy();
エンハンサーエンハンサー=新しいエンハンサー();
enhancer.setSuperclass(StudentService.class)。
enhancer.setCallback(cglibProxy)。
StudentService 0 =(StudentService)enhancer.create();
System.out.println(o.getName())。
//するSystem.out.println(o.getID());
}
}
それ以上のOは、実際のStudentserviceメソッドにアクセスすることができますプロキシクラスです。
結果:無錫婦人科のチェックどのくらいのお金http://www.120csfkyy.com/
++++++ $ 1 CGLIB $のgetNameに前++++++
getName
------ ------のgetName
++++++ $ 1 CGLIB $のgetNameに前++++++
トム
使用CGLIBだから何の利益?
以下のコードを見てください:
パブリッククラスTestCglib {
パブリック静的無効メイン(文字列[] args){
CglibProxy cglibProxy =新しいCglibProxy();
エンハンサーエンハンサー=新しいエンハンサー();
enhancer.setSuperclass(StudentService.class)。
enhancer.setCallback(cglibProxy)。
StudentService 0 =(StudentService)enhancer.create();
System.out.println(o.getName())。
//するSystem.out.println(o.getID());
エンハンサーenhancer1 =新しいエンハンサー();
enhancer1.setSuperclass(UserServiceImpl.class)。
enhancer1.setCallback(cglibProxy)。
UserServiceImpl OBJ =(UserServiceImpl)enhancer1.create();
System.out.println(obj.getName(1))。
//するSystem.out.println(o.getID());
}
}
ただ書きます
cglibProxy
達成することができます
StudentServiceためUserServiceImplプロキシ
面倒なコードを減らすため、1つのエージェントのみが、簡単なメンテナンス、デカップリング、続く、十分であり、問題がある場合に限り、元のクラスがそれに行くためにと