AOP proxy mechanism series (four) SpringAOP in

A, AOP implementation of the principles underlying the Spring

The principle underlying the Spring AOP are Java's dynamic proxy technology .

Second, the dynamic proxy

principle

At runtime, dynamically generated proxy class .class file in some way, technology is relatively common and Cglib JAVA dynamic proxy agent.

classification

JAVA dynamic agent technology

You must define an interface

public interface Animal {

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

Implementation class Cat

public class Cat implements Animal {


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

Implementation class Dog

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("方法执行后");
    }

}
复制代码

Test generate proxy classes

 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("狗粮");
    }
复制代码

Output:

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

System.getProperties (). Put ( "sun.misc.ProxyGenerator.saveGeneratedFiles", "true"), this sentence will generate proxy classes in the local paper.

//
// 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());
        }
    }
}

复制代码

image

  • Generate a proxy class object
 Proxy.newProxyInstance(Cat.class.getClassLoader(), new Class[]{Animal.class}, new AnimalHandler(cat));
复制代码
  • Looking proxy class, start looking for the cache
 
 private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());


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

This code execution and analysis of the above processes, parameters ClassLoader class loader, class interfaces, Handler implementation class. Source code analysis, may generate a proxy class know, then totally reflects method of obtaining interface, and implement methods, then through h.invoke () method call a method of the original object.

cglib dynamic agent technology

Here you can define classes or interfaces

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);
    }
}

复制代码

Definition method interceptors


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("方法执行后");
    }


}
复制代码

testing method:

    @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("狗粮");
    }

复制代码

Output:

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

Third, the comparison proxy mode

Compare factors JAVA Dynamic Proxy Cglib agent
Easy to use Convenience Convenience
Generation mode Dynamic bytecode Dynamic bytecode
Generation efficiency 13ms / a 217ms / a
operating efficiency 2224 ms, 634,022 t/s 1123 ms, 1,255,623 t/s

Spring agent technology in only JAVA Cglib dynamic proxy agents and, in addition also generates a proxy-based technology JAVAASSIST and ASM.

Fourth, the reference

blog.csdn.net/riemann_/ar…

Guess you like

Origin juejin.im/post/5db1bc81f265da4d3b1298df