デザインパターンプロキシモード(Javaの例)と春AOP機能への応用

プロキシモード:

モデルの一種として作用する必要がエージェントをプロキシすることを橋の使用であり、エージェントは、プロキシ対象となるエージェントのニーズに最初のクラスではなく、ときに、このオブジェクトを使用する必要がある他のオブジェクトにプロキシクラスを介してプロキシオブジェクトに直接移動します。これは、プロキシクラスのプロキシオブジェクトによって向上させることができます。プロキシモードでは、静的および動的プロキシエージェントに分割されています。

静的なエージェント:

静的手段プロクシオブジェクト剤誰組み合わせによって、インターフェイスを実装するために、プロキシクラスによって達成され、セット、上のコンパイル時。

例:

プロキシクラスのインタフェース:

パッケージcom.ustc。

パブリック インターフェースサブ{
     公共 ボイドのdoSomething(); 
}

プロキシクラス:

パッケージcom.ustc。

輸入java.sql.SQLOutput; 

パブリック クラス SubImpの実装のサブ{ 

    @Override 
    公共 のボイドのdoSomething(){ 
        System.out.printlnは( "私が行っています" ); 
    } 
}

演技のカテゴリ:

パッケージcom.ustc、

パブリック クラス SubProxy 実装のサブ{
    // プロキシクラスの組合せによって増強される実施ニーズ
    プライベートサブオブジェクト= NULL ; 

    公共SubProxy(){ 
    } 
    公共SubProxy(サブオブジェクト){
         この .Object = オブジェクト。
    } 
    @Override 
    公共 のボイドのdoSomething(){
         // エージェントの強化クラスはここにある 
        のSystem.out.println(「オブジェクトは、技術を向上させる」);
         // コールプロキシクラスに対応するオブジェクトのこの方法では 
        subProxy subProxy = 新新 SubProxy(新新SubImp()); 
        subProxy.object.doSomething(); 
        // 処理プロキシオブジェクト後 
        のSystem.out.println( "ハンドル代を" ); 
    } 
}

あなたは、コンパイル時に決定されたプロキシオブジェクトエージェントを見ることができるので、欠点があります:各エージェントは、プロキシクラスを実装するために、そのプロキシとプロキシクラスへのプロキシクラスであることを持っている必要がありますすべてのインターフェイスメソッド、高い冗長コード。====「ダイナミックエージェントは、この欠点を補うことができます。

動的プロキシ

プロキシオブジェクトは、動的にはいプロキシオブジェクトである実行時に決定されたプロキシオブジェクトを作成するために反射によって、コンパイル時に実行時に決定されていません。これは、コードの再利用性を向上させることができます。(プロキシされて、各オブジェクトのプロキシクラスを作成するには、管理大幅に強化率のプロキシクラスとメソッドを持っていません)。

最初に導入:動的プロキシクラスのインターフェースおよび方法は異なり。

インタフェースのInvocationHandler

公式の説明:

InvocationHandler演技はの一例である呼び出しハンドラを実装します。

各プロキシインスタンスには、関連する呼び出しハンドラを持っています。プロキシインスタンスのメソッド呼び出しは、メソッド呼び出しは、符号化され、呼び出し元のハンドラに割り当てinvoke方法。 

実際には、プログラムの一部が静的プロキシクラスがプロキシインタフェースによって上書きさに相当します。(しかし、この方法は、リフレクションを介して呼び出されます)

彼は、インターフェイスを実装するための唯一の必要性です:

 

 

 

 

 

3つのパラメータを意味:

 3つのパラメータを呼び出します。
オブジェクトのプロキシ:プロキシオブジェクト
方法方法:(反射によって)オブジェクトの現在記載された方法を実行するプロキシオブジェクト
オブジェクト[]引数:実際のプロセスパラメータ
どのように動的プロキシオブジェクトを作成するには?
たとえば、Proxy.newProxyInstance

 

彼の三つのパラメータ:

パラメータ:

loader - プロキシクラスのクラスローダを定義     

interfaces - 実装するためのインタフェースのプロキシクラスのリスト   

 h - 割り当てメソッド呼び出しハンドラの呼び出し 

ダイナミックプロキシインスタンス:

パッケージcom.ustc; 

インポートjava.lang.reflect.InvocationHandler;
 インポートjava.lang.reflect.Methodオブジェクト、
 インポートjava.lang.reflect.Proxyの、

パブリック クラスSubDynamicProxy {
     公共  SubDynamicProxy createSubDynamicProxy(文字列[]引数){
         // まだ達成組み合わせることにより 
        サブサブ= 新しい新しいSubImp();
         // 動的に生成されたプロキシオブジェクトを 
        。SubDynamicProxyプロキシ=(SubDynamicProxy)たとえば、Proxy.newProxyInstance(SubDynamicProxy クラス .getClassLoader()、sub.getClass()でgetInterfaces()。新しい新規のInvocationHandlerの(){ 
            @Override 
            公衆呼び出しオブジェクト(オブジェクトO、メソッド、メソッド、オブジェクト[]引数)スローのThrowable {
                 // ターゲットメソッド実行する前に、拡張メソッドを 
                するSystem.out.println(「標的前メソッド技術の強化を」);
                 // ターゲットメソッドの呼び出し、およびターゲットを得る方法結果返される 
                オブジェクト結果= Method.invoke(SUB、引数);
                 // ターゲットメソッドの実行は、エンハンスメント後 
                のSystem.out.printlnを(「ターゲットメソッドの後に技術を向上させる」);
                 戻り結果を; 
            } 
        }); 
        戻りプロキシ; 
    } 
}

使用するために必要なときにそのSubImpプロキシクラスを介して得ることができ、SubImp法を増強することにより増強することができます。もう一つの利点:インタフェースは変更がないときは、プロキシクラスがそれを変更する必要はありません別の動的プロキシクラスのエージェントを達成するために見て、そのエージェントクラスのインタフェースですか?このような結合は、多くのことを低減します。

春AOPアプリケーションの動的プロキシー:

AOP(アスペクト指向プログラミング):AOPは、長手方向の継承の伝統的なアーキテクチャを置き換える横抽出機構を使用します。

その上にこの文を理解するには?

シナリオを想像:

基底クラスがあり、我々はどのように行う伝統的な、強化する必要がありますか?===「継承は、その伝統的な縦の継承と呼ばれ、垂直です。

今、我々は、横方向の抽出によって(拡張メソッド内に配置され)強化クラスの、すなわち、製造を有し、従って、クラスベースの同じレベルで強化を高める上で、次にソートクラスにこれらの2つの方法の組み合わせを介してプロキシクラスは、到達していません効果を結合度を減らすために、継承を回避しながら、目的を強化?

春AOPの例:

プロキシされるために必要なクラスおよびインタフェース:

パブリック インターフェースUserServiceの{
       公共 ボイドアドユーザー();
      公共 のボイドupdataUser();
      公共 のボイドdeleUsr(); 
} 
// ターゲット:需要被代理的类
パブリック クラス UserServiceImp 実装UserServiceの{ 
      @Override 
      公共 ボイドアドユーザー(){
              // TODO自動生成方法スタブ 
             のSystem.out.println( "アドユーザー" )。
      } 
      @Override 
      公共 ボイドupdataUser(){
              //TODO自動生成方法スタブ 
             のSystem.out.println(「updateUser」)。
             
      } 
      @Override 
      公共 ボイドdeleUsr(){
              // TODO自動生成方法スタブ 
             のSystem.out.println( "deleUser" )。
             
      } 
}

カットクラス:(拡張を防ぎます)

パブリック クラス MyAspect 実装org.aopalliance.intercept.MethodInterceptor { 
      @Override 
      パブリックオブジェクトを呼び出し(MethodInvocation MI)はスローたThrowable { 
             するSystem.out.println( "前の" )。
             // 调用目标方法 
             オブジェクト進む= mi.proceed()。
             System.out.println( "后" );
             戻る進みます。
      } 
}

そして、書き込みの設定ファイルに、春の植物は、設定ファイル(ここで使用されるフレームワークAspectJのAOP、自己ビュー)を介してプロキシクラスを生成

<?xmlのバージョン= "1.0"エンコード= "UTF-8"> 
<豆のxmlns = "http://www.springframework.org/schema/beans" 
      のxmlns:XSI = "http://www.w3.org / 2001 / XMLスキーマ・インスタンス" 
      のxmlns:AOP = "http://www.springframework.org/schema/aop" 
      のxsi:schemaLocationの =" http://www.springframework.org/schema/beans 
      のhttp:// WWW。 springframework.org/schema/beans/spring-beans.xsd 
             ます。http:// www.springframework.org/schema/aop 
             ます。http:// www.springframework.org/schema/aop/spring-aop.xsd "> 
      <! - -把目标类交给スプリング- > 
    <ビーンID = "userServiceId"クラス = "com.ustc.AOP.auto.UserServiceImp"> </豆> 
      <! -春にカットクラスへ- >
      <豆IDは=「myAspectId」クラス </ビーン> =「com.ustc.AOP.auto.MyAspect」> 
エントリポイントと一致する:それらポイントカットを接続することによりaopconfig :!ポイントカット式- <を。どの方法を強化する必要性です。- > <! -顧問:特別なセクション、通知のみとエントリポイントのポイントカット- REF:このセクションでは、アドバイス-refの通知のためのエントリポイントです。セクションにそれらを一緒に入れて- > <! - *ターゲットクラス、AspectJのポイントカット表現、インポートジャーパッケージを判断するには- > <! - Com.springsource.org.aspectj.weaver.jar - > < ! -ポイントカット表現:.実行(com.ustc.AOP.auto.UserServiceImp * * (..) - > <AOP:config>の <AOP:=ポイントカット表現「実行(* com.ustc.AOP。 。auto.UserServiceImp *(..)) "ID =" myPointCut "/> <AOP:アドバイス-REF = Advisorは" myAspectId "ポイントカット-REF =" myPointCut "

 

そのプロキシオブジェクトを取得することです再取得UserServiceの後。実際には、春の形成機構は、動的プロキシプロキシオブジェクトです。

動的プロキシ機構は、スプリングAOPの底部に使用されるソースによって検証されます。

AOPプロキシの構造:

 

 

 接続がない場合、動的プロキシ・インターフェースがある場合、それは、唯一CGLIBバイトコード実装クラスを使用します。

AOPプロキシインタフェース

パブリック インターフェイスAopProxy { 

    / ** 
     *新しいプロキシオブジェクトを作成します。
     (プロキシを作成するために必要な場合)* <pは> AopProxyのデフォルトのクラスローダを使用します:
     *通常、スレッドコンテキストクラスローダを。
     * @return 新しいプロキシオブジェクトを(決して{ @codeのヌル})
    オブジェクトgetProxy()。

    / ** 
     *新しいプロキシオブジェクトを作成します。
     * <P>(プロキシ作成のために必要であれば)指定されたクラスローダを使用します。
     * { @codeのヌル}は単に渡されるので、ローレベルにつながる
     選択デフォルトと通常異なる*プロキシ機能のデフォルトを
     * AopProxy実装の{によって@link #getProxy()}メソッド。
     * @param でプロキシを作成するためのクラスローダクラスローダ
     (または{* @codeの低レベルのプロキシ機能のデフォルトにnull})
    オブジェクトgetProxy(@NullableのClassLoaderクラスローダ)。

}

プロキシクラスを取得し、その方法を表示するために、たとえば強化動的プロキシを取ります

動的プロキシSpringAOPを生成する方法であって:

パブリックオブジェクトgetProxy(@NullableのClassLoaderクラスローダ){
         場合(logger.isTraceEnabled()){ 
            logger.trace( "JDKの動的プロキシを作成する:" + この.advised.getTargetSourceは())。
        } 
        クラス [] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(<?> これは、.advised )。
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces)。
        返すたとえば、Proxy.newProxyInstance(クラスローダ、proxiedInterfaces、これを)。
    } 

    / ** 
     *任意{検索@link #equals}または{ @linkを定義されてもよい#hashCode}メソッド
     インターフェースの付属セットに*。
     * @paramのproxiedInterfacesイントロスペクトインターフェイス
      * / 
    プライベート ボイド findDefinedEqualsAndHashCodeMethods(クラス<?> [] proxiedInterfaces){
         ため(クラス<?> proxiedInterface:proxiedInterfaces){ 
            方法[]メソッド = proxiedInterface.getDeclaredMethods()。
            以下のために(方法のメソッド:メソッド){
                 場合(AopUtils.isEqualsMethod(メソッド)){
                     この .equalsDefinedは= 
                }
                もし(AopUtils.isHashCodeMethod(メソッド)){
                     この .hashCodeDefinedは= 
                } 
                であればこの .equalsDefined && この.hashCodeDefined){
                     リターン
                } 
            } 
        } 
    }

トップコードは非常に精通していないですか?特に、この1:

たとえば、Proxy.newProxyInstance(クラスローダ、proxiedInterfaces、これを返します)。

プロキシモードでは、先に紹介し、動的プロキシです。

したがって、この方法は、インタフェースプロキシクラスを用いる基礎となるSpringAOP動的プロキシ機構を実装しています。

春AOPは、アドレスに対応するMavenのリポジトリを伴って、ダウンロードおよびビューにMavenのリポジトリにソースを表示することができます。

  https://repo1.maven.org/maven2/springframework/spring-aop/

 

 リミテッドは、エラーがある、と指摘してください!

おすすめ

転載: www.cnblogs.com/tlxclmm/p/12005391.html