博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈Java代理一:JDK动态代理-Proxy.newProxyInstance
阅读量:6772 次
发布时间:2019-06-26

本文共 5578 字,大约阅读时间需要 18 分钟。

浅谈Java代理一:JDK动态代理-Proxy.newProxyInstance

 

 

  • java.lang.reflect.Proxy:该类用于动态生成代理类,只需传入目标接口、目标接口的类加载器以及InvocationHandler便可为目标接口生成代理类及代理对象。
// 方法 1: 该方法用于获取指定代理对象所关联的InvocationHandlerstatic InvocationHandler getInvocationHandler(Object proxy) // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象static Class getProxyClass(ClassLoader loader, Class[] interfaces) // 方法 3:该方法用于判断指定类是否是一个动态代理类static boolean isProxyClass(Class cl) // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

 

JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的;但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。

要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。在java中如何用程序去生成一个对象的代理对象呢,java在JDK1.5之后提供了一个"java.lang.reflect.Proxy"类,通过"Proxy"类提供的一个newProxyInstance方法用来创建一个对象的代理对象,如下所示:

 

示例业务逻辑:

1-娱乐明星都会唱歌、演习(interface Star)

2-有一个明星叫胡歌(class HuGe implements Star)

3-他有两个助理(分别对应两个代理类)(class HuGeProxy1、class HuGeProxy2)

4-如果要找胡歌唱歌、演戏,需要先找两个助理中的一个,然后助理去找胡歌唱歌、演戏(class ProxyTest)

 

package com.huishe.testOfSpring.proxy;//定义一个明细接口public interface Star {    void sing(String song);//唱歌        String act(String teleplay);//表演}

 

package com.huishe.testOfSpring.proxy;//创建胡歌类-实现明细接口public class HuGe implements Star{    public void sing(String song) {        System.out.println("胡歌演唱: " + song);    }    public String act(String teleplay) {        System.out.println("胡歌决定出演电视剧: " + teleplay);        return "胡歌答应出演电视剧: " + teleplay;    }}

 

package com.huishe.testOfSpring.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//胡歌代理类1//使用一个匿名内部类来实现该接口实现InvocationHandler接口,实现invoke方法public class HuGeProxy1 {    private Star hg = new HuGe();//实例化一个对象        public Star getProcxy(){        //使用Proxy.newProxyInstance(ClassLoader loader, Class
[] interfaces, InvocationHandler h)返回某个对象的代理对象 /** * ClassLoader loader:Java类加载器; 可以通过这个类型的加载器,在程序运行时,将生成的代理类加载到JVM即Java虚拟机中,以便运行时需要! * Class
[] interfaces:被代理类的所有接口信息; 便于生成的代理类可以具有代理类接口中的所有方法 * InvocationHandler h:调用处理器; 调用实现了InvocationHandler 类的一个回调方法 * */ return (Star)Proxy.newProxyInstance( getClass().getClassLoader(), hg.getClass().getInterfaces(), new InvocationHandler() { /** * InvocationHandler接口只定义了一个invoke方法,因此对于这样的接口,我们不用单独去定义一个类来实现该接口, * 而是直接使用一个匿名内部类来实现该接口,new InvocationHandler() {}就是针对InvocationHandler接口的匿名实现类 */ /** * 在invoke方法编码指定返回的代理对象干的工作 * proxy : 把代理对象自己传递进来 * method:把代理对象当前调用的方法传递进来 * args:把方法参数传递进来 * * 当调用代理对象的star.sing("逍遥叹");或者 star.act("琅琊榜")方法时, * 实际上执行的都是invoke方法里面的代码, * 因此我们可以在invoke方法中使用method.getName()就可以知道当前调用的是代理对象的哪个方法 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("sing")){ System.out.println("我是胡歌代理1,找胡歌唱歌找我"); return method.invoke(hg, args); } if(method.getName().equals("act")){ System.out.println("我是胡歌代理1,找胡歌演电视剧找我"); return method.invoke(hg, args); } return null; } }); }}

 

 

package com.huishe.testOfSpring.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//胡歌代理类2//实现InvocationHandler接口,实现invoke方法public class HuGeProxy2 implements InvocationHandler{    private Star hg = new HuGe();        public Star getProcxy(){        return (Star)Proxy.newProxyInstance(                getClass().getClassLoader(),                 hg.getClass().getInterfaces(),                 this);    }    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                if(method.getName().equals("sing")){            System.out.println("我是胡歌代理2,找胡歌唱歌找我");            return method.invoke(hg, args);        }        if(method.getName().equals("act")){            System.out.println("我是胡歌代理2,找胡歌演电视剧找我");            return method.invoke(hg, args);        }                return null;    }            }

 

package com.huishe.testOfSpring.proxy;import org.junit.Test;public class ProxyTest {    //测试代理类1    @Test    public void testHuGeProxy1(){                HuGeProxy1 proxy = new HuGeProxy1();//找到胡歌的助理        Star hg = proxy.getProcxy();//助理和胡歌洽谈        hg.sing("《逍遥叹》");//(胡歌答应后)唱歌        String actResult = hg.act("《琅琊榜》");//(胡歌答应后)演习        System.out.println("演出结果:" + actResult);    }    //测试代理类1    @Test    public void testHuGeProxy2(){                HuGeProxy2 proxy = new HuGeProxy2();        Star hg = proxy.getProcxy();        hg.sing("《逍遥叹》");        String actResult = hg.act("《琅琊榜》");        System.out.println("演出结果:" + actResult);    }    }

 

 

代理1日志输出: 我是胡歌代理1,找胡歌唱歌找我胡歌演唱: 《逍遥叹》我是胡歌代理1,找胡歌演电视剧找我胡歌决定出演电视剧: 《琅琊榜》演出结果:胡歌答应出演电视剧: 《琅琊榜》代理2日志输出:我是胡歌代理2,找胡歌唱歌找我胡歌演唱: 《逍遥叹》我是胡歌代理2,找胡歌演电视剧找我胡歌决定出演电视剧: 《琅琊榜》演出结果:胡歌答应出演电视剧: 《琅琊榜》

 

 

参考资料:

1-https://www.cnblogs.com/xdp-gacl/p/3971367.html

2-https://blog.csdn.net/justloveyou_/article/details/79407248

转载于:https://www.cnblogs.com/wobuchifanqie/p/9991342.html

你可能感兴趣的文章
阿里开源分布式事务解决方案 Fescar 全解析
查看>>
D2 日报 2019年1月4日
查看>>
iOS数据结构与算法实战 二叉树总结篇
查看>>
2019年吐血推荐的Chrome扩展
查看>>
说说在 Python 中如何传递任意数量的实参
查看>>
Framework在iOS中地运用以及配置
查看>>
React 性能优化总结
查看>>
HashMap到底是怎么put的?
查看>>
【解决】Xcode9断点无法停在代码区
查看>>
深入V8引擎-默认Platform之mac篇(2)
查看>>
深入理解ThreadLocal
查看>>
深圳APP开发婚恋社交App
查看>>
ES6 -- String 扩展方法解析
查看>>
算力大战是BCH最坏的一种处理方式
查看>>
Java 设计模式(五)《装饰器模式》
查看>>
Mob之社会化分享集成ShareSDK
查看>>
node识别es6的 import/export
查看>>
JavaScript中浏览器兼容代码
查看>>
SpringCloud微服务云架构构建B2B2C电子商务平台之-(九)服务链路追踪(Spring Cloud Sleuth)...
查看>>
(五) 整合spring cloud云服务架构 - 云架构代码结构构建
查看>>