动态代理

静态代理:

就是一种组合方式的,A类组合目标类,A类A方法中引用目标类的a方法;对其进行辅助实现;
若想调用目标类的a方法,直接可以用A类A方法代理执行;

1.动态代理:

JDK动态代理:就是字节码重组过程,主要是生成新的代理类并实现目标类全部方法;

<font color=Red> 因为是通过实现,被代理类都实现接口 </font>

JDK动态代理过程
1.首先通过getInstance获取目标类,然后通过反射获取其全部方法;
2.Proxy.newProxyInstance通过入参:类的classLoader, 类的接口方法,该JDKDemoPorxy;
来创建新的代理对象;并且实现全部接口方法;

Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
  1. 最终通过invoke 来调用方法;入参:新生成的代理类,调用的目标方法,方法入参 ;
    作用对原有类的接口方法做业务增强,比如before(),after()等方法;
public Object invoke(Object proxy, Method method, Object[] args)

4.根据上述动态生成java代码,编译新生产的.class文件,重新加载到JVM运行

//具体使用例子

//jdk代理类
public class JDKDemoPorxy implements InvocationHandler {
    private Object target;
    public Object getInstance(Object target) throws Exception {
        this.target = target;
        Class<?> clazz = target.getClass();
        //反射获取目标类方法,并新生成一个代理类,并实现全部方法,其中invoke可以做逻辑切入
        //入参类的classLoader,类的接口,该JDKDemoPorxy
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }
    //入参:新生成的代理类,调用的目标方法,方法入参
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object obj = method.invoke(this.target, args);
        after();
        return obj;
    }
    private void before() throws Exception {
        System.out.println("before+++");
    }
    private void after() {
        System.out.println("after+++");
    }
}
public interface Person {
    void getName();
    Long getCreateTime(String param);
}

//目标类
public class Customer implements Person {
    @Override
    public void getName() {
        System.out.println("sally");
    }
    @Override
    public Long getCreateTime(String param) {
        System.out.println(param);
        return System.currentTimeMillis();
    }
}
//测试使用
public class JDKProxyTest {
public static void main(String[] args) throws Exception {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        Person student = (Person) new JDKMeipo().getInstance(new Customer());
        student.getCreateTime();

//        Person customer = (Person) new CglibProxyDemo().getInstance(Customer.class);
//        customer.getName();
    }
}

代理重组字节码反编译后生成的文件:

通过反编译新的代理类文件$Porxy;可以看到 他实现了所有方法,并在static静态块中用反射找到所有方法以m0,m1,m2....来命名方法

public final class $Proxy0 extends Proxy implements Person {
    private static Method m1;
    private static Method m3;
    private static Method m4;
    private static Method m2;
    private static Method m0;
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    public final boolean equals(Object var1) throws  {省略}
    public final void getName() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final Long getCreateTime() throws  {
        try {
            return (Long)super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final String toString() throws  {省略}
    public final int hashCode() throws  { 省略}
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.example.springbootdemo.model.Person").getMethod("getName");
            m4 = Class.forName("com.example.springbootdemo.model.Person").getMethod("getCreateTime");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

2.CGlib动态代理

CGlib动态代理原理:是通过生成子类继承目标类,并覆盖;

CGlib动态代理过程
1.首先通过Enhancer,设置目标类,并设置代理为回调,生成代理类继承目标类;

public Object getInstance(Class<?> clazz) throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        //生成代理类继承目标类
        return enhancer.create();
    }

2.当调用代理类中方法时,通过MethodInterceptor拦截或说回调到intercept,来触发MethodProxy.invokeSuper;

@Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        before();
        //methodProxy invokeSuper触发并生FastClass类,通过FastClass机制
        Object obj = methodProxy.invokeSuper(o,args);
        after();
        return obj;
    }
若缓存中没有,其中为目标类和代理类各生成一个FastClass类,这类会为每个方法分配一个index;
FastClassInfo fci = fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);

获取当前代理类的FastClass类和index,当作入参就可以直接调用方法,省去反射调用;所以比JDK执行效率高;
FastClass不是和代理一起生成的,而是在第一次执行MethodProxy.invokeSuper生成的,并放在缓存中;

使用例子

public class CglibProxyDemo implements MethodInterceptor {

    public Object getInstance(Class<?> clazz) throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        //生成代理类继承目标类
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        before();
        //methodProxy invokeSuper触发并生FastClass类,通过FastClass机制
        Object obj = methodProxy.invokeSuper(o,args);
        after();
        return obj;
    }


    private void before() throws Exception {
        System.out.println("before+++");
    }

    private void after() {
        System.out.println("after+++");
    }
}
public class  CglibProxyTest {
    public static void main(String[] args) throws Exception {
        Person customer = (Person) new CglibProxyDemo().getInstance(Customer.class);
        customer.getName();
    }
}

代理类调用方法时,会MethodInterceptor拦截进入intercept,触发methodProxy.invokeSuper(o,args);
MethodProxy是很关键的,调用invokeSuper时,为目标类和代理类各生成一个FastClass类,这类会为每个方法分配一个index;
获取代理类的FastClass根据index,调用方法;

public class MethodProxy {

    private Signature sig1;
    private Signature sig2;
    private CreateInfo createInfo;
    private final Object initLock = new Object();
    private volatile FastClassInfo fastClassInfo;
···
  private void init() {
        if (fastClassInfo == null) {
            synchronized (initLock) {
                if (fastClassInfo == null) {
                    CreateInfo ci = createInfo;

                    FastClassInfo fci = new FastClassInfo();
                    fci.f1 = helper(ci, ci.c1);
                    fci.f2 = helper(ci, ci.c2);
                    fci.i1 = fci.f1.getIndex(sig1);
                    fci.i2 = fci.f2.getIndex(sig2);
                    fastClassInfo = fci;
                    createInfo = null;
                }
            }
        }
    }
。。。
  private static class FastClassInfo {
        FastClass f1;
        FastClass f2;
        int i1;
        int i2;
    }
。。。。
  public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
                        //生成FastClass类 ,若有就从缓存中获取
            init();
            FastClassInfo fci = fastClassInfo;
                        //根据fci.i2的index,去调用方法
            return fci.f2.invoke(fci.i2, obj, args);
        }
        catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }
」

推荐阅读更多精彩内容