JDK动态代理原理实现

持有被代理类对象的类称为代理类。

JDK实现动态代理的对象必须实现接口,为什么一定要实现接口?

## 创建接口类

public interface Human {

    void createHourse();
}

## 创建被代理对象

public ITHuman implements Human {

    @Override
    public void cereateHourse() {
        
        System.println.out("我要一所大房子");

    }    
}

## 创建代理类

public class HourseProxy implements InvocationHandler {

    private Object target;

    public HourseProxy(Object target) {

        this.target = target;
    }

    public static Object getProxyInstance() {
        
        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("正在帮你筛选房源信息");
        Object obj = method.invoke(target, args);
        System.out.println("你已经拥有了一栋新房子");
        return obj;
    }
    

}
public class ProxyTest {

    public static void main(String[] args) {

        HourseProxy proxy = new HourseProxy(new ITHuman());
        Human me = (Human)proxy.getProxyInstance();
        /** com.sun.proxy.$Proxy4 */
        //以$开头的类都是动态生成的
        System.out.println(me.getClass());
        human.createHourse();
       
    }
}

  打印信息............... 

class com.sun.proxy.$Proxy4
正在帮你筛选房源信息
我要一所大房子
你已经拥有了一栋新房子

可以看到代理对象的类名是以 刀略$Proxy开始的,下面来看看这个动态代理类的代码:

如何来获取这个代理类的呢?注意文件目录里面是找不到的,

         //通过反编译工具查看源代码
        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy4", new Class[]{Human.class});
        FileOutputStream outputStream = new FileOutputStream("//Users//pengy//$Proxy4s.class");
        outputStream.write(bytes);
        outputStream.close();
import com.gupao.mode.proxy.Human;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy4 extends Proxy implements Human {
    private static Method m1;
    private static Method m2;
    private static Method m5;
    private static Method m0;

    public $Proxy4(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 createHourse() throws  {
        try {
            super.h.invoke(this, m5, (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"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m5 = Class.forName("com.gupao.mode.proxy.Human").getMethod("createHourse");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

从上可知,我们在main中调用human.createHourse() 的时候实际上是调用的代理类$Proxy4中的createHourse()方法,

JDK动态代理原理实现 

JDK动态代理原理实现 

既然是调用的代理类那么invoke方法当然是代理类中的invoke方法,然后通过反射来调目标方法,到这里对动态代理的思想是不是更深一步呢。还是挺有意思的嘛

 

 动态代理原理:字节码重组

                          1.生成Java 文件

                          2.将java文件写到磁盘

                          3.编译成class 文件

                          4.将class文件加载到JVM中

步骤一生成Java文件就是上面的$Proxy4, 回到了没有IDE的时代,记事本写Java文件,那可是一个标点符号都不错的哦。