JAVA中JDK的动态代理反射实现

    技术2025-03-30  37

    目录

    大白话解释动态代理

    代码简单实现


    大白话解释动态代理

       动态代理是代理中的一种,代理分为静态代理和动态代理。代理有点像我们生活中的代理商,下面我们就拿 手机交易 举例,手机交易至少涉及到两个角色 ,手机生产厂商(producer) 与 买手机的顾客consumer 。手机交易有两种方式,一种 是 producer 与 consumer 直接接触完成交易(有点远古人类的交易),另外一种是 手机生产厂商producer与消费者consumer的交易通过第三方完成,producer 和 consumer没有直接接触,第三方就是我们要说的手机代理商proxy。在商品交易的过程中,producer的行为动作是 拿出手机,获得金钱(货币)回报;而consumer的行为动作是付出金钱,换回手机。在交易过程中,不管通过哪一种方式来完成,producer 和 consumer的行为动作 都是不变的。与直接接触完成交易一样,通过 代理完成的交易,producer的行为 动作还是拿出手机,获得金钱回报,consumer的 行为动作是 拿出金钱 换回 的是手机,两种方式唯一的不同的是,在 producer 与 proxy的交易中,proxy扮演的是 consumer角色,而 proxy 与 consumer的交易中,proxy扮演的是 producer角色,但是实际上,proxy既 没有真正消费手机,也没有需要付出金钱给 producer,而只是起到中间商的作用,producer的最终手机去向和金钱来源其实都是 手机消费者 consumer,consumer该付出的钱还得付,得到 的还是手机。这就是代理的解释。想要解释动态代理,我们必须得配合静态代理的解释。市面上有很多手机品牌,静态代理有点像一个代理商 proxy 只 代理一种手机,那样岂不是需要很多很多的代理商?实际上手机代理商会代理很多品牌的手机,对于消费者来说,消费者consumer想要购买什么品牌的手机,我proxy就是什么品牌手机的代理商,而不再是规定死死的一种手机代理商,这就动态的手机代理商,动态代理。

    代码简单实现

      代码实现的场景还是参照上面的解释,手机消费者consumer与手机代理商,我们省略 手机生产商producer。

      创建一个手机消费者接口 MobilePhoneConsumer ,一个 购买手机的方法buyPhone package com.atustb.ref; public interface MobilePhoneConsumer { //购买手机的抽象方法,返回手机名称。实际业务中返回的是手机对象 String buyPhone(double money); } 创建两个手机消费者实现类:华为 消费者HuaweiPhoneConsumer与 OPPO消费者OppoPhoneConsumer package com.atustb.ref; // OPPO手机消费者 public class OppoPhoneConsumer implements MobilePhoneConsumer { @Override public String buyPhone(double money) { System.out.println("oppo 聆听, 如此优雅"); return "OPPO"; } } package com.atustb.ref; //华为手机消费者 public class HuaweiPhoneConsumer implements MobilePhoneConsumer { @Override public String buyPhone(double money) { System.out.println("永不放弃,华为手机与您一起"); return "华为"; } }

    现在我们要通过手机代理商进行购买,动态代理要解决的问题有两个,第一个就是 根据消费者的类型来决定到底是创建哪种类型的手机代理,所以我们得出在创建 动态代理的时候的输入是 消费者的类型,第二个就是 消费者与手机代理之间是怎么交互的,毫无疑问,消费者拿出金钱,换回的还是手机,也就是说consumer的购买手机动作没有变法,代理商消费手机也就是相当于consumer消费手机,所以我们知道在手机代理商购买手机的底层还是要consumer购买手机的。

    创建动态代理,首先我们定义在代理商购买手机的时候应该怎么处理consumer的购买行为,我们通过自定义InvocationHandler来实现。 package com.atustb.ref; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //定义代理怎么与真正消费者 consumer 的交互逻辑 public class ConsumerInvocationHandler<T> implements InvocationHandler { // obj 就是我们真正的消费者 private T obj; public void bind(T obj){ this.obj = obj; } //通过反射调用 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(obj,args); } } 定义动态代理类 ConsumerProxy package com.atustb.ref; import java.lang.reflect.Proxy; public class ConsumerProxy { /** * 因为java中的多态是 运行时行为,我们让 动态代理与 消费者类型 实现 一样的接口 * @param obj 我们根据消费者类型创建对应的代理类,obj 就是传进来的消费者类型 * @param <T> * @return 返回一个动态代理对象 */ public static <T> T getProxyInstance(T obj){ ConsumerInvocationHandler<T> tHandler = new ConsumerInvocationHandler<>(); tHandler.bind(obj); // obj.getClass().getClassLoader() 让 动态代理类 使用与 消费者 obj一样的类加载器加载 // obj.getClass().getInterfaces() 获取的就是消费者所属类实现的接口 // tHandler 定义动态代理对象怎么与真正的消费者直接应该怎么进行交互 return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),tHandler); } } 测试 package com.atustb.ref; import org.junit.Test; public class ConsumerProxyTest { @Test public void test1(){ //华为消费者 MobilePhoneConsumer huawConsumer = new HuaweiPhoneConsumer(); MobilePhoneConsumer proxyInstance = ConsumerProxy.getProxyInstance(huawConsumer); System.out.println("买的手机是 " + proxyInstance.buyPhone(300)); System.out.println("************************************************"); //OPPO消费者 OppoPhoneConsumer oppoPhoneConsumer = new OppoPhoneConsumer(); MobilePhoneConsumer oppoProxyInstance = ConsumerProxy.getProxyInstance(oppoPhoneConsumer); System.out.println("买的手机是 " + oppoProxyInstance.buyPhone(300)); } }

    测试结果 

    Processed: 0.010, SQL: 9