Java动态代理之JDK动态代理Proxy类

注:示例代码如下

public interface ProxyInterface {

    String targetMethod(String param);

}
public class JDKProxy {


    public Object getInstanceProxy(Class c) {
        Object instance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{c}, (proxy, method, args) -> {
            System.out.println("代理被执行。。。。");
            System.out.println("执行完毕");
            if (args != null) {
                System.out.println("参数:" + args[0]);
            }
            return "您好";
        });
        return instance;
    }

}
public class ProxyInterfaceMain {
    public static void main(String[] args) {
        JDKProxy jdkProxy = new JDKProxy();
        ProxyInterface instanceProxy = (ProxyInterface) jdkProxy.getInstanceProxy(ProxyInterface.class);
        System.out.println(instanceProxy.targetMethod("你好"));
//        System.out.println(instanceProxy);
    }
}

JDK的动态代理可以通过Proxy类型newProxyInstance()方法实现,方法有三个参数

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

JDK的动态代理生成,只能为接口提供,也就是说,有以下两种情况

1、接口没有实现类
如果接口没有实现类,那么生成的代理对象,在invoke方法中,则不能调用method.invoke方法,因为接口没有实现,调用这个方法传入proxy则会死循环,传入接口的类型,将会报错,则,接口所有的方法,都只能走InvocationHandler的invoke方法逻辑
而且,如果没有实现类,在调用Proxy.newProxyInstance时,要注意传入的interfaces参数,没有实现类,则需要用new Class[]{ProxyInterface.class}的方法传入,这样就可以生成代理了,如果传的是new Class[0],那么默认只会给toString方法代理,具体在下面有说明
2、
如果接口有实现类,那么在调用Proxy.newProxyInstance时,就需要用实现的Class对象,调用getInterface()方法,得到这个类实现的接口数组,然后这样代理对象才能对实现类的所有接口进行代理。
在这里插入图片描述

  1. ClassLoader loader
    类加载器,一般都是直接获取当前线程的类加载器,也可以传入自定义的
    获取当前线程类加载器:
Thread.currentThread().getContextClassLoader()

为什么要传入ClassLoader(类加载器、CL)

JVM通过类加载器来将.class文件加载到Meta space(元空间)中,也就是会通过类加载器,创建一个类的Class对象
JDK的动态代理,是一种动态字节码技术,通过在JVM中直接写入字节码的方式,为原始类创建一个代理类
再结合前面说的,如果要为这个代理类创建一个代理对象,则需要通过类加载器将代理类加载(创建一个代理类的Class对象)
而由于代理类是动态生成的,所以没有对应的类加载器,则只能通过方法参数传递进来(借用一个类加载器)。

  1. Class<?>[] interfaces
    需要代理的接口,这个参数有点特殊,它可以传入需要代理的接口的class,也可以传入接口中的方法的class
    1、传入接口的class
    在这里插入图片描述
    那么代理则会生成这个接口的实现类,在调用接口中的方法时,会执行InvocationHandler的invoke()方法,返回值也是方法的返回值,就是走的正常的动态代理流程
    2、传入数组大小问0的Class数组
    在这里插入图片描述
    如果是这样传值的话,那么,代理的接口就是toString()方法,且不能将返回的对象强转为接口类型,因为返回值对象已经变成了,invoke方法返回的,也只有在使用返回值对象时,才会触发invoke方法
    例如:
    在这里插入图片描述
    在这里插入图片描述

  2. InvocationHandler
    代理对象,通过动态代理生成出的对象,调用对象方法,实际调用的就是InvocationHandler对象的invoke方法,可以自定义一个类,实现InvocationHandler接口,也可以在Proxy.newProxyInstance的时候通过lambda表达式实现invoke方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值