JDK动态代理是如何实现的

911 阅读2分钟

代理

Java SDK代理

Java SDK 是一种基于对象的代理

Java SDK 是一种面向接口的代理

Java 代码实现

接口定义

public interface Transfer {
	void speed();
}

子类实现

public class Car implements Transfer {

    private String name;
    private String type;

    public String getName() {
        return name;
    }

    public String getType() {
        return type;
    }

    @Override
    public String toString() {
        return "Car{" + "name='" + name + '\'' + ", type='" + type + '\'' + '}';
    }

    /**
     * 继承父类方法
     */
    @Override
    public void speed() {
        System.out.println("car, so fast");
    }

    /**
     * 子类方法
     */
    public void form() {
        System.out.println("三厢");
    }
}

InvocationHandler 实现

public class MyInvocationHandler implements InvocationHandler {

		
	  private Object **target**;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object = null;
        System.out.println("invoke before ....");
        object= method.invoke(target,args);
        System.out.println("invoke after ...");
        return object;
    }
}

调用生效

import sun.misc.ProxyGenerator;

import java.lang.reflect.Proxy;

public class JavaSDKProxyDemo {

    public static void main(String[] args) {

        Car car = new Car();
        Transfer proxy = (Transfer) Proxy.newProxyInstance(Transfer.class.getClassLoader(), new Class[]{Transfer.class}, new MyInvocationHandler(car));
        proxy.speed();
        
        //生成代理类   -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true (保存代理类信息)
        //ProxyGenerator.generateProxyClass("$MyTransferProxy", new Class[]{Transfer.class});

    }
}

执行结果

invoke before ....
car, so fast
invoke after ...

从生成的代理类看Java SDK 动态代理的运行机制

$MyTransferProxy类定义

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

    public $MyTransferProxy(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 speed() 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("代理.javaSDK代理.Transfer").getMethod("speed");
            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());
        }
    }
}
  • $MyTransferProxy 构造方法会将 InvocationHandler 传递给Super类,也就是Proxy类
  • 代理方法 speed() 的调用会委托给super类中的 InvocationHandler对象的invoke方法执行,也正是我们自定义的MyInvocationHandler的invoke方法

类图

Untitled.png

从代理类源码和类图可以看到:
1、Java SDK动态代理是基于接口实现:目标类、代理类都实现同一接口;
2、动态生成的代理类继承Proxy类,持有InvocationHandler具体实现类对象;
3、InvocationHandler具体实现类将Car类作为成员变量

调用逻辑就变得清晰明了:
 //调用代理类的方法,转而调用Proxy类中持有InvocationHandler对象(也就是我们自己实现的MyInvocationHandler的invoke方法)
 super.h.invoke(this, m3, (Object[])null);
 

问题

Proxy类在生成代理类的时候,为什么要显式穿ClassLoader?

 Transfer proxy = (Transfer) Proxy.newProxyInstance(Transfer.class.getClassLoader(), new Class[]{Transfer.class}, new MyInvocationHandler(car));