动态代理与CGLib

Posted wqff-biubiu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理与CGLib相关的知识,希望对你有一定的参考价值。

一、动态代理是利用Java反射机制实现的

JAVA反射机制:在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

类加载过程中的加载过程会在内存中生成一个代表此Class文件的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。通过这个Class的实例对象,可以知道这个类的所有属性和方法.

JDK中反射包java.lang.reflect则提供了操作这个类的任意方法和属性的设计。java.lang.reflect包中主要实体类Method、Field、Constructor分别对应着类的方法、属性及构造方法,

另外反射包中的Proxy类与InvocationHandler接口是实现了动态代理的超类与接口

java.lang.reflect.Proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

java.lang.reflect.InvocationHandler是代理实例的调用处理程序 实现的接口。

二、动态代理的实现例子

public class DynamicProxyTest {
interface IHello{ void sayHello(); } static class Hello implements IHello{ @Override public void sayHello() { System.out.println("hello world"); } } static class DynamicProxy implements InvocationHandler{ Object target; Object bind(Object target){ this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("welcome"); return method.invoke(target,args); } } public static void main(String[] args){ IHello target = new Hello(); System.out.println(target.getClass().getClassLoader()); System.out.println(Arrays.toString(target.getClass().getInterfaces())); System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");//在对应package下生成代理类$Proxy0.class IHello hello = (IHello) new DynamicProxy().bind(target); hello.sayHello(); } }
其中Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this)这行代码生成的代理类$Proxy0.class,如下
package com.sun.proxy;

import com.app.proxy.IHello;
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 IHello {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    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 void sayHello() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    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 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"));
            m3 = Class.forName("com.app.proxy.IHello").getMethod("sayHello");
            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());
        }
    }
}
可以看出生成的代理类
继承了Proxy,实现了target.getClass().getInterfaces()--IHello,组合了this--构造方法中super(InvocationHander)
不仅实现了被代理类接口的方法sayHello,另外重写了toString,hashCode,equals方法,但格式都是一样的
super.h.invoke(this,mx,new Object[]{varx});//super.h.invoke即invocationHandler接口的实现类DynamicProxy.invoke(),
这样导致代理类的hashCode,toString与被代理类的hashCode,toString
一样,但是实际类型是不同的。下面是一些验证
public static void main(String[] args) {
        IHello target = new Hello();
        IHello hello = (IHello) new DynamicProxy().bind(target);
        System.out.println("target.toString:"+target.toString());//target.toString:com.app.proxy.Hello@eed1f14
        System.out.println("target.hashCode:"+target.hashCode());//target.hashCode:250421012
        System.out.println("proxy.toString:"+hello.toString());//proxy.toString:com.app.proxy.Hello@eed1f14
        System.out.println("proxy.hashCode:"+hello.hashCode());//proxy.hashCode:250421012
        System.out.println("target == proxy:"+(target == hello));//target == proxy:false
        hello.sayHello();
}

 



以上是关于动态代理与CGLib的主要内容,如果未能解决你的问题,请参考以下文章

Spring AOP JDK动态代理与CGLib动态代理区别

JDK动态代理与CGLIB动态代理

JDK动态代理与CGLIB动态代理

DK动态代理与CGLib动态代理的区别

JDK 动态代理与 CGLIB 动态代理,它俩真的不一样

JDK的动态代理与cglib动态代理