Jdk动态代理源码

Proxy

代码: java.lang.reflect.Proxy

Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

构造一个新的Proxy实例,并指定调用处理器 InvocationHandler。

    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

InvocationHandler

InvocationHandler 经常和 Proxy 配合使用。

InvocationHandler是由代理实例的调用处理程序实现的接口。

每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,方法调用会被编码并分派给其调用处理程序的 invoke 方法。

public interface InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

Proxy 和 InvocationHandler 代码示例

可以通过一个简单的示例, 了解下 Proxy 和 InvocationHandler 的使用。

  • MyInterface :
public interface MyInterface {

    String doSomething();
}

  • MyInterfaceImpl :
public class MyInterfaceImpl implements MyInterface {

    @Override
    public String doSomething() {
        System.out.println("MyInterfaceImpl doSomething");
        return "doSomething result";
    }

}

  • MyInvocationHandler:
public class MyInvocationHandler implements InvocationHandler {

    /**
     * 目标对象
     */
    private final Object target;

    /**
     * 调用处理器的构造方法,以目标对象作为参数
     * @param target
     */
    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //以下是一个简单的 AOP

        //前置处理
        System.out.println("before doSomething.");
        //反射,调用目标对象的方法
        Object result = method.invoke(target, args);
        //后置处理
        System.out.println("after doSomething.");

        return result;
    }


}

  • ProxyDemo 示例:
public class ProxyDemo {
    public static void main(String[] args) throws Exception {
        //保存代理产生的类文件,方便查看 com.sun.proxy.$Proxy0 的源码
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

        //被代理的目标对象
        MyInterface myInterfaceImpl = new MyInterfaceImpl();
        //自定义调用处理器 InvocationHandler , 以目标对象为参数
        InvocationHandler invocationHandler = new MyInvocationHandler(myInterfaceImpl);

        //Jdk动态代理支持的 Class对象必须是一个接口,否则会报错 IllegalArgumentException:is not an interface
        MyInterface myInterface = (MyInterface) Proxy.newProxyInstance(
                MyInterface.class.getClassLoader(),
                new Class<?>[] { MyInterface.class },
                invocationHandler);
        //调用的实际是动态代理生成的 com.sun.proxy.$Proxy0 对象的 doSomething()方法
        myInterface.doSomething();

    }

}

源码 com.sun.proxy.$Proxy0

com.sun.proxy.Proxy0 继承了Proxy类,并实现了示例代码中的 MyInterface。
示例中加入以下代码,会保存代理产生的类文件,方便查看 com.sun.proxy.Proxy0 的源码。

        //保存代理产生的类文件,方便查看 com.sun.proxy.$Proxy0 的源码
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

为什么调用代理对象的方法,就会调用自定义的 MyInvocationHandler 中的 invoke()方法?
可以看一下 com.sun.proxy.$Proxy0的源码。运行示例代码后,会自动生成这个类。

实际上调用的是父类Proxy的 InvocationHandler h 的 invoke()方法。
也就是示例代码中的 MyInvocationHandler类的 invoke() 方法。

public final class $Proxy0 extends Proxy implements MyInterface {
    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 String doSomething() throws  {
        try {
            //为什么调用代理对象的方法,就会调用自定义的 MyInvocationHandler 中的 invoke()方法
            //实际上调用的是父类Proxy的 InvocationHandler h 的 invoke()方法。
            //也就是示例代码中的 MyInvocationHandler类的 invoke() 方法。
            return (String)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,就是要被代理的目标接口 MyInterface 的 doSomething方法
            m3 = Class.forName("com.example.demo.sourceCode.proxy.MyInterface").getMethod("doSomething");
            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.newProxyInstance

源码: java.lang.reflect.Proxy#newProxyInstance

newProxyInstance() 是代理类经常用的方法。

newProxyInstance() 方法返回指定接口的代理类实例,该代理类将方法调用分派给指定的调用处理程序(InvocationHandler)。

    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * 查找或生成指定的代理类。
         */
        Class<?> cl = getProxyClass0(loader, intfs);


        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            
            //使用指定的调用处理程序(InvocationHandler)调用其构造函数。
            //Constructor构造方法的 newInstance() 是支持 InvocationHandler转换为 Object 作为参数的。
            return cons.newInstance(new Object[]{h});
            
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

Jdk 动态代理的缺点

Jdk 动态代理 只支持接口级别的动态代理, 如果提供的不是接口,就会报错:

java.lang.IllegalArgumentException:  is not an interface

源码:java.lang.reflect.Proxy.ProxyClassFactory#apply

  //验证Class对象是否实际表示接口。如果不是接口,就会报错。
  if (!interfaceClass.isInterface()) {
      throw new IllegalArgumentException(
          interfaceClass.getName() + " is not an interface");
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值