AOPプロキシ機構シリーズ(4)SpringAOPで

春の基礎となる原則の、AOPの実装

春AOPの基礎となる原則は、Javaの動的プロキシ技術

第二に、動的プロキシ

原則

実行時には、何らかの方法で動的に生成されたプロキシクラスの.classファイルは、技術は比較的一般的とCGLIB JAVAダイナミックプロキシエージェントです。

分類

JAVAダイナミックエージェント技術

あなたは、インターフェイスを定義する必要があります

public interface Animal {

    void  eat(String food);
}
复制代码

実装クラスキャット

public class Cat implements Animal {


    @Override
    public void eat(String food) {
        System.out.println(Cat.class.getSimpleName()+" eat:"+food);
    }
}
复制代码

実装クラスの犬

public class Dog implements Animal {


    @Override
    public void eat(String food) {
        System.out.println(Dog.class.getSimpleName()+" eat:"+food);
    }
}

复制代码
public class AnimalHandler implements InvocationHandler {

    private Animal target;

    public AnimalHandler(Animal target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        //这里可以修改参数
        StringBuilder  stringBuilder=new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            stringBuilder.append("param"+(i+1)+":"+args[i]).append(",");
        }
        if (stringBuilder.length()>1){
            System.out.println(stringBuilder.subSequence(0,stringBuilder.length()-1));
        }
        System.out.println("method:"+method.getName());
        Object ret=method.invoke(target,args);
        after();
        return ret;
    }

    /**
     * 方法执行前
     */
    private void before() {
        System.out.println("方法执行前 !");
    }

    /**
     * 方法执行后
     */
    private void after() {
        System.out.println("方法执行后");
    }

}
复制代码

テストは、プロキシクラスを生成します

 public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        Animal cat = new Cat();
        //找到代理对象
        Animal catProxy = (Animal) Proxy.newProxyInstance(Cat.class.getClassLoader(), new Class[]{Animal.class}, new AnimalHandler(cat));
        System.out.println(catProxy.getClass().getSimpleName());
        catProxy.eat("猫粮");

        Animal dog = new Dog();
        Animal dogProxy = (Animal) Proxy.newProxyInstance(Dog.class.getClassLoader(), new Class[]{Animal.class}, new AnimalHandler(dog));
        System.out.println(dogProxy.getClass().getSimpleName());

        dogProxy.eat("狗粮");
    }
复制代码

出力:

$Proxy0
方法执行前 !
param1:猫粮
method:eat
Cat eat:猫粮
方法执行后
$Proxy0
方法执行前 !
param1:狗粮
method:eat
Dog eat:狗粮
方法执行后
复制代码

System.getProperties()。(「sun.misc.ProxyGenerator.saveGeneratedFiles」、「真」)に入れ、この文は地元紙にプロキシクラスを生成します。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.yuntian.firstspringboot.proxy.Animal;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Animal {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void eat(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.yuntian.firstspringboot.proxy.Animal").getMethod("eat", Class.forName("java.lang.String"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

复制代码

画像

  • プロキシクラスのオブジェクトを生成します
 Proxy.newProxyInstance(Cat.class.getClassLoader(), new Class[]{Animal.class}, new AnimalHandler(cat));
复制代码
  • プロキシクラスを見ると、キャッシュを探し始めます
 
 private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());


 Class<?> cl = getProxyClass0(loader, intfs);
复制代码

このコードが実行されると上記の方法の分析は、ClassLoaderクラスローダは、クラスインターフェースハンドラ実装クラスパラメータ。ソースコード解析、プロキシクラスを生成することがわかっている場合、完全に界面を得る方法を反射し、メソッドを実装し、h.invokeスルー()メソッドは、元のオブジェクトのメソッドを呼び出します。

CGLIBダイナミックエージェント技術

ここでは、クラスやインタフェースを定義することができます

public abstract class AbstartAnimal {

    public abstract void eat(String food);

}
复制代码
public class CatTest extends AbstartAnimal {


    @Override
    public void eat(String food) {
        System.out.println(CatTest.class.getSimpleName()+" eat:"+food);
    }
}

复制代码
public class DogTest extends AbstartAnimal {


    @Override
    public void eat(String food) {
        System.out.println(DogTest.class.getSimpleName()+" eat:"+food);
    }
}

复制代码

定義方法インターセプタ


import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class AbstratAnimalInterceptor implements MethodInterceptor {

    /**
     * 被增强的类
     */
    private AbstartAnimal target;

    public AbstratAnimalInterceptor(AbstartAnimal target) {
        super();
        this.target = target;
    }

    /**
     * 用来产生代理对象
     */
    public  Object createProxy() {
        // 增强类
        Enhancer enhancer = new Enhancer();
        // 设置增强类的回调方法
        enhancer.setCallback(this);
        //设置代理类的父类
        enhancer.setSuperclass(AbstartAnimal.class);
        return enhancer.create();
    }


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object ret = method.invoke(target, objects);
        after();
        return ret;
    }


    /**
     * 方法执行前
     */
    private void before() {
        System.out.println("方法执行前 !");
    }

    /**
     * 方法执行后
     */
    private void after() {
        System.out.println("方法执行后");
    }


}
复制代码

試験方法:

    @Test
    public void testcglibProxy() {

        AbstartAnimal cat = new CatTest();
        AbstratAnimalInterceptor interceptorCat = new AbstratAnimalInterceptor(cat);
        AbstartAnimal catProxy = (AbstartAnimal) interceptorCat.createProxy();
        catProxy.eat("猫粮");

        AbstartAnimal dog = new DogTest();
        AbstratAnimalInterceptor interceptorDog = new AbstratAnimalInterceptor(dog);
        AbstartAnimal dogProxy = (AbstartAnimal) interceptorDog.createProxy();
        dogProxy.eat("狗粮");
    }

复制代码

出力:

方法执行前 !
CatTest eat:猫粮
方法执行后
方法执行前 !
DogTest eat:狗粮
方法执行后
复制代码

第三に、比較プロキシモード

要因の比較 JAVA動的プロキシ CGLIBエージェント
使いやすいです 便利 便利
生成モード ダイナミックなバイトコード ダイナミックなバイトコード
発電効率 13msの/ A 217ms / A
業務の効率化 2224ミリ秒、634022トン/秒 1123ミリ秒、1255623トン/秒

のみJAVA CGLIB動的プロキシエージェントのばねエージェント技術と、他にも、プロキシベースの技術JAVAASSISTとASMを生成します。

第四に、参照

blog.csdn.net/riemann_/ar...

おすすめ

転載: juejin.im/post/5db1bc81f265da4d3b1298df