Java面接知識点(80)設計モードのエージェントモード(下)

14078 ワード

前章で述べたJava面接知識点(七十九)設計モデルのエージェントモデル(上)の静的エージェントと動的エージェントモードは,いずれもターゲットオブジェクトが1つのインタフェースを実現するターゲットオブジェクトであることを要求するが,ターゲットオブジェクトが単独のオブジェクトであり,インタフェースが実現されていない場合があり,この場合,ターゲットオブジェクトのサブクラスでクラス実装エージェントを実装する方法をCglibエージェントと呼ぶ.
Cglibエージェントは、サブクラスエージェントとも呼ばれ、メモリにサブクラスオブジェクトを構築することで、ターゲットオブジェクトの機能拡張を実現する.CGLibは非常に下位層のバイトコード技術を採用しており、その原理はバイトコード技術によって1つのクラスのためにサブクラスを作成し、サブクラスの中で方法でブロックする技術を採用してすべての親クラスの方法の呼び出しをブロックし、勢いに乗って横断論理を織り込むことである.ただし継承を採用しているためfinal修飾のクラスをエージェントすることはできない.JDK動的エージェントとCGLib動的エージェントはいずれもSpring AOPを実現する基礎である.
Cglibサブクラスエージェントの実装方法:
  • はcglibのjarファイルを導入する必要があります.
  • 機能パッケージを導入すると、メモリにサブクラス
  • を動的に構築することができる.
  • エージェントのクラスはfinalではありません.そうしないと、
  • とエラーが発生します.
  • ターゲットオブジェクトのメソッドがfinal/staticである場合、ブロックされない、すなわちターゲットオブジェクトの追加のビジネスメソッドは実行されない.

  • 【コード例】
  • ターゲットオブジェクト
  • package designpatterns.proxy.Cglib;
    
    /**
     *      
     * */
    public class Child {
        public void school() {
            System.out.println("     ");
        }
    
        public void money() {
            System.out.println("     ");
        }
    }
    
    
  • エージェントクラス(エージェントクラスがターゲットオブジェクトのサブクラスを生成する)
  • package designpatterns.proxy.Cglib;
    
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class Proxy implements MethodInterceptor {
    
        //       
        private Object object;
    
        public Proxy(Object object) {
            this.object = object;
        }
    
        //            
        public Object getProxy() {
            //      
            Enhancer en = new Enhancer();
            //     
            en.setSuperclass(object.getClass());
            //       ,           interce  
            en.setCallback(this);
            //     (    )
            return en.create();
        }
    
    	/**
         *        ,                ,                
         * */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
            //          
            Object result = null;
    
            if ("school".equals(method.getName())) {
                result = method.invoke(this.object, objects);
            }
    
            if ("money".equals(method.getName())) {
                System.out.println("     ");
            }
    
            return result;
        }
    }
    
    
  • 試験環境
  • package designpatterns.proxy.Cglib;
    
    public class Demo {
        public static void main(String[] args) {
            Child proxy = (Child) new Proxy(new Child()).getProxy();
    
            proxy.school();
            proxy.money();
        }
    }
    
    
  • 運転結果
  •      
         
    

    【まとめ】
    1.javaを間違えました.lang.NoClassDefFoundError: org/objectweb/asm/Type
    インポートされたjarパケットが不完全または不整合である場合、エージェントモードはcglibである2つのjarパケットをインポートする必要がある.jar;もう一つはasm.JAr(バイトコードの処理);cglibのみをインポートするとコンパイルできますが、実行中に問題が発生し、インポートされたバージョンが間違っていたり、エラーが発生したりします.私はcglib 3を使っています.1.jarとバイトコードasm 4.0.jar;コードテストを経て、直接使用できます.皆さんはネット上でcglib関連jarパッケージを探したりクリックしたりしてダウンロードすることができます.
    2.invokeとinvokeSuperの違いを分析する
    MethodInterceptインタフェースを実装する際にはinterceptメソッドも実装する必要があります.このメソッドは親をブロックするためのメソッドです.つまり、エージェントの子が継承するターゲットの親のメソッドです.エージェントの子がブロックした後に論理を書き換えてエージェントの役割を果たしますが、親を取得する方法には以下のような方法があります.
    result = method.invoke(this.object, objects);
    result = methodProxy.invokeSuper(o,objects);
    result = methodProxy.invoke(this.object,objects);
    

    interceptメソッドのパラメータは次のとおりです.
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
  • Object o:サブクラスオブジェクト
  • Method method:親メソッドオブジェクト
  • Object[]objects:メソッドパラメータ配列
  • MethodProxy methodProxy:サブクラスメソッドオブジェクト
  • invokeとinvokeSuper
    invokeメソッド呼び出しのオブジェクトは強化されておらず、invokeSuperメソッド呼び出しのオブジェクトはすでに強化されている(ブロック後に論理が変更された)ので、MyMethodInterceptorのinterceptorメソッドをもう一度繰り返し、ブロックチェーンであれば、再びブロックチェーンを歩きます.
    invokeSuperは増強後の方法であるため,invokeSuperのパラメータはサブクラスである.
  • Object o:サブクラスオブジェクト