JDK动态代理的底层实现

JDK动态代理

相信大家都会了解过或用过JDK动态代理,下面附一段经典火车站卖票案例代码作为引入

//卖票接口
interface SellTickets {
    void sell();
}

//火车站 火车站具有卖票功能,所以需要实现SellTickets接口
class TrainStation implements SellTickets {
    public void sell() {
        System.out.println("火车站卖票");
    }
}

//代理工厂,用来创建代理对象
public class ProxyFactory {
    private TrainStation station = new TrainStation();

    public SellTickets getProxyObject() {
//使用Proxy获取代理对象
/*
newProxyInstance()方法参数说明:
ClassLoader loader : 类加载器,用于加载代理类,使用真实对象的类加载
器即可
Class<?>[] interfaces : 真实对象所实现的接口,代理模式真实对象和代
理对象实现相同的接口
InvocationHandler h : 代理对象的调用处理程序
*/
        SellTickets sellTickets = (SellTickets)
                Proxy.newProxyInstance(station.getClass().getClassLoader(),
                        station.getClass().getInterfaces(),
                        new InvocationHandler() {
                            /*
                            InvocationHandler中invoke方法参数说明:
                            proxy : 代理对象
                            method : 对应于在代理对象上调用的接口方法的 Method 实
                            例
                            args : 代理对象调用接口方法时传递的实际参数
                            */
                            public Object invoke(Object proxy, Method method,
                                                 Object[] args) throws Throwable {
                                System.out.println("代理点收取一些服务费用(JDK动态代理方式)");
//执行真实对象
                                Object result = method.invoke(station, args);
                                return result;
                            }
                        });
        return sellTickets;
    }
}

//测试类
class Client {
    public static void main(String[] args) {
//获取代理对象
        ProxyFactory factory = new ProxyFactory();
        SellTickets proxyObject = factory.getProxyObject();
        proxyObject.sell();
    }
}

动态代理类是程序在运行过程中动态的在内存中生成的类。所以要通过阿里巴巴开源的 Java 诊断工具(Arthas【阿尔萨斯】)查看代理类的结构,结构如下(为了方便看懂结构,我把代码进行了精简)

//程序运行过程中动态生成的代理类
public final class $Proxy0 extends Proxy implements SellTickets {
    private static Method m3;
    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }
    static {
        m3=Class.forName("com.yjq.proxy.dynamic.jdk.SellTickets").getMethod("sell", new Class[0]);
    }
    public final void sell() {
        this.h.invoke(this, m3, null);
    }
}

我们可以看到$Proxy0类是在内存中生成的代理类,实现了SellTickets接口。
当我们调用代理类的sell方法时,实际执行的是

public final void sell() {
        this.h.invoke(this, m3, null);
    }

变量 InvocationHandler h是父类里面的成员变量,那我们来看一下父类Proxy的代码(简化版)

public class Proxy implements java.io.Serializable {
        protected InvocationHandler h;
        protected Proxy(InvocationHandler h) {
            this.h = h;
        }
    }

看到这,所有逻辑都打通了吧。

总结一下就是:JDK的Proxy类在我们调用方法newProxyInstance时,生成一个代理对象在内存中,该对象根据参数实现了SellTickets接口,重写接口的sell()方法。在此方法内,调用了我们创建的InvocationHandlerinvoke()方法。实际调用的就是InvocationHandler中我们重写的invoke方法。所以动态代理在运行时会根据我们重写的代码进行增强

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值