Java動的エージェントと反射メカニズムの詳細な解説


反射メカニズム
Java言語が提供する基礎機能は、反射によって、このクラスまたはオブジェクトを操作して、例えば、このクラスの方法、属性、構造方法などを取得することができます。
ダイナミックエージェント:JDKダイナミックエージェント、cglibダイナミックエージェント(spring中のダイナミックエージェント)に分けられます。
スタティックエージェント
事前に(コンパイル期間)代理人と被代理人との関係を確定しました。つまり、プロキシ類がプログラムを実行する前にすでに存在している場合は、スタティックエージェントといいます。
ダイナミックエージェント
プロキシクラスは、プログラム運転時に作成されるプロキシ方式です。つまり、プロキシクラスはJavaコードで定義されているのではなく、実行中にJavaコードの「指示」に従って動的に生成されます。
動的エージェントの利点は、静的エージェントに比べて:
動的エージェントは、各プロキシクラスの関数を変更する代わりに、プロキシクラスの関数を均一に処理するのに便利であり、より柔軟で拡張的である。
 JDKのダイナミックエージェント(インターフェース依存)
  • は、Javaの動的エージェント機構において、2つの重要なクラスまたはインターフェースがあり、1つはInvocationHandlerインターフェースであり、もう1つはProxyタイプである。
  • InvocationHandlerインターフェースは、動的エージェントクラスに実装され、プロキシ対象の動作
  • の処理を担当する。
  • Proxyクラスは、動的エージェントクラスのインスタンスオブジェクトを作成するために使用され、このオブジェクトを得るだけで、プロキシが必要な方法を呼び出すことができる。
  • 動的エージェントのエージェントは、静的エージェントクラスで修正され、動的エージェントクラスは、InvocationHandlerインターフェースを実現し、Invoke方法を書き換え、Invoke方法は、着信されたプロキシ方法とパラメータによって実行される。
  • 以下の例:
    
    public interface AppService {
     void createApp(String name);
     void deleteApp(String name);
    }
     
    //   (      )
    public class AppServiceImpl implements AppService{
     
     @Override
     public void createApp(String name) {
      System.out.print("App["+name+"] has been created.");
     }
     
     @Override
     public void deleteApp(String name) {
      System.out.print("App["+name+"] has been delete.");
     }
    }
     
     
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
     
    public class LoggerInterceptor implements InvocationHandler {
     private Object target; //   (    )   ,    
     public LoggerInterceptor(Object target){ 
      this.target = target; 
     } 
     @Override
     public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
      System.out.println("Entered "+target.getClass().getName()+"-"+method.getName()+",with arguments{"+args[0]+"}"); 
      Object result = method.invoke(target, args);
      //          (       (createApp)   (Kevin Test))
      System.out.println("Before return:"+result); 
      return result; 
     }
     
    }
    
    import java.lang.reflect.Proxy;
     
    public class test {
     
    public static void main(String[] args) {
        AppService target = new AppServiceImpl();//       (      )
        //         
        AppService proxy = (AppService) Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(), new LoggerInterceptor(target));
        proxy.createApp("Kevin Test1");
        proxy.deleteApp("Kevin Test2");
      }
     
    }
     
    /**
    * 1、jdk                ,              。
    * 2、  proxy                  。
    * 3、          InvocationHandler   invoke      
    *
    *  java        ,          ,   InvocationHandler  、      Proxy ,                     。
    InvocationHandler            ,             , Proxy               ,                          。
    *
    *           
    proxy:        
    method:         
    args:             
       :            
    *
    *   :
    *    Proxy  newProxyInstance        ,          createApp() deleteApp()  ,
    *        2      invoke()     。  proxy               ,            AppService
    *
    */
    cglibダイナミックエージェント(継承方式)
    cglibダイナミックエージェントでは、動的エージェントクラスを実現するためにMethodInterceptorを使用する。
    スクリーンセーバーMethodInterceptorでは、MethodProxyのInvokSuper方法でプロキシ方法を呼び出します。
    MethodProxy類は代理方法と代理方法の署名を生成する。
    JDKダイナミックエージェントとCglibダイナミックエージェントの違い:
  • JDK動的エージェントは、代行対象のインターフェースを実装し、Cglibは、代行対象を継承している。
  • Cglibは継承機構ですので、finalで修飾された方法を代理できません。
  • JDKとCglibは運行中にバイトコードを生産します。JDKは直接にクラスのバイトコードを書きます。CglibはASMフレームを使ってクラスのバイトコードを書きます。cglibエージェントの実装はより複雑で、生成エージェントはJDKより効率が低い。
  • JDKは、反射によるメカニズム呼び出しであり、cglibはFashclass機構による直接的な呼び出し方法であり、より効率的である。
  •  Fastcassの仕組み:
    エージェントクラスと被エージェントクラスのためにクラスを生成し、このクラスはエージェントクラスまたはエージェントクラスの方法にindexを割り当てる。
    このindexは参席として、Fashclassは呼び出される方法を直接的に位置決めして呼び出されます。これは反射を省きますので、効率がいいです。
    以上は小编が绍介したJava动态代理と反射メカニズムを详しく整理しました。皆さんに助けてほしいです。もし何か疑问があれば、メッセージをください。小编はすぐに皆さんに返事します。ここでも私たちのサイトを応援してくれてありがとうございます。