Java动态代理技术-我的浅显认识
来源:互联网 发布:我的世界自动攻击js 编辑:程序博客网 时间:2024/05/18 02:12
说到代理,大家不由想到23种设计模式中的代理模式。JDK的动态代理技术正是基于代理模式,并且核心使用了反射机制实现的。首先,便于理解,我们看看demo级别的代理模式(也就对应地叫做静态代理):
interface Person {public void doSomething(); } class User implements Person { public void doSomething() { System.out.print("基类方法"); } } class Proxy implements Person { User user; public Proxy() { // 初始类时得到被代理类的实例 this.user = new User(); } public void doSomething() { System.out.print("前-"); user.doSomething(); System.out.print("-后"); } } ///////////////////////////////////////////////////////////////////////////////// public void main(String[] strs){ Person proxy=new Proxy(); proxy.doSomething(); }
输出:前-基类方法-后
对于以上实现,我们发现了静态代理模式的一些繁琐之处:每需要代理一个类时,需要程序员手动为其构造类似如上代理类代码。于是JDK出现了动态代理技术来解决这一窘境。下面先看看它的基本使用方式:
对于以上实现,我们发现了静态代理模式的一些繁琐之处:每需要代理一个类时,需要程序员手动为其构造类似如上代理类代码。于是JDK出现了动态代理技术来解决这一窘境。下面先看看它的基本使用方式:
// 调用处理器:代理类的相应方法被执行会均会调用该处理器,而该处理器则会调用被代理类方法完成操作 class MyInvocationHandler implements InvocationHandler {private Object metaObj;public MyInvocationHandler(Object obj) {this.metaObj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.print("前-");Object obj = method.invoke(metaObj, args); System.out.println("-后"); return obj;} } ///////////////////////////////////////////////////////////////////////////////// public static void main(String[] args) {MyInvocationHandler myHandler = new MyInvocationHandler(new User());Person proxy= (Person) Proxy.newProxyInstance(User.class.getClassLoader(), User.class.getInterfaces(),myHandler);proxy.doSomething();}
输出:前-基类方法-后
对于以上就是动态代理的一个简单使用,我们可以发现:使用动态代理,我们将能够应对任何需要代理的类,并为其生产代理类。仅需要在调用生成代理实例的newProxyInstance方法时传入适当的参数(该类的类加载器,该类所实现的所有接口,调用处理器)。我们来看看它的大概实现,下面给出关键代码(我只是将核心代码进行内联,便于观看,其实远不止这点代码):
@CallerSensitive public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){ Class<?> proxyClass = null; //待生成的代理类的类类型 //根据提供的接口生成代理类字节数组流。ProxyGenerator为rt.jar包中负责生成代理类字节数组流工具,proxyName为生成的代理 //class文件的名字,由省略代码给出 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces); //由类加载器将字节数组流生成为一个新类,并加载到内存中,然后返回其类类型。 proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); //根据代理类的类类型获取其中含有{ InvocationHandler.class } 参数的构造器 final Constructor<?> cons = proxyClass .getConstructor({ InvocationHandler.class }); //根据该构造器,实例化代理类,并让调用处理器进入该实例中 return cons.newInstance(new Object[] {h} ); }
由上代码,我们可以看到,通过指定类装载器和一组相关接口就可以生成代理类实例。而InvocationHandler调用处理器仅是作为一个参数进入到了生成的这个实例中。那么此时有两个问题:
1.上面含有{ InvocationHandler.class } 参数的构造器是怎么产生的?
代理类起自ProxyGenerator.generateProxyClass方法,究其实现可发现如下代码:
methods.add(generateConstructor()); private MethodInfo generateConstructor()throws IOException{ MethodInfo methodinfo = new MethodInfo("<init>", "(Ljava/lang/reflect/InvocationHandler;)V", 1); DataOutputStream dataoutputstream = new DataOutputStream(methodinfo.code); code_aload(0, dataoutputstream); code_aload(1, dataoutputstream); dataoutputstream.writeByte(183); dataoutputstream.writeShort(cp.getMethodRef("java/lang/reflect/Proxy", "<init>", "(Ljava/lang/reflect/InvocationHandler;)V")); dataoutputstream.writeByte(177); methodinfo.maxStack = 10; methodinfo.maxLocals = 2; methodinfo.declaredExceptions = new short[0]; return methodinfo; }
很明显,构造器就是在这里被加入进去的,且参数类型明确指出是Ljava/lang/reflect/InvocationHandler。
2.InvocationHandler的作用又到底是什么呢?
先看看代理类生成为class文件的相关核心代码:
public final void doSomething(){ this.invocationHandler.invoke(this, m3, null); //this表示代理类实例 return; } static{ m3 = Class.forName("My程序.动态代理.Person").getMethod("doSomething", new Class[0]); return; }结合调用处理器看: // 调用处理器:代理类的相应方法被执行会均会调用该处理器,而该处理器则会调用被代理类方法完成操作 class MyInvocationHandler implements InvocationHandler {private Object metaObj;public MyInvocationHandler(Object obj) {this.metaObj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.print("前-");Object obj = method.invoke(metaObj, args); System.out.println("-后"); return obj;} }
我们需要让代理类去管控被代理类(代理模式设计原则),也就是比如在调用之前或者之后能进行一些额外操作(如上面的“前-”、“-后”)。而代理类都是运行时动态生成的,那么这些额外操作怎么才能放进去呢?这时,InvocationHandler作用就出现了。额外操作的编码就放在Invocation中,然后让InvocationHandler进入动态生成的代理类实例,实例来调用InvocationHandler的方法即可。
1 0
- Java动态代理技术-我的浅显认识
- 关于java JDK动态代理的浅显理解
- java 泛型的浅显认识
- jamvm的浅显认识
- Java泛型(浅显认识)
- java动态代理技术
- java动态代理之我的理解
- 动态代理 静态代理 代理模式详解(讲的很好 浅显易懂)
- 关于WebService的浅显认识
- Java中的动态代理技术
- java技术-静态代理到动态代理
- 谈谈java代理模式的认识二——动态代理(JDK)
- 谈谈java代理模式的认识二——动态代理(JDK)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM) (清晰,浅显)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM) (清晰,浅显)
- session和cookie在php应用中我进一步的浅显认识
- 从头认识java-12.5 代理以及动态代理
- JDK动态代理的一些认识
- Linux系统中文件下的Access/Modify/Change
- programme
- 三层架构和MVC模式
- 数字图像处理的基本概念
- 记录一次因为redis aof rewrite重写导致的运维过程
- Java动态代理技术-我的浅显认识
- JSON学习笔记
- 百度谷歌雅虎搜狗提交链接入口
- C/C++ | 字符串处理 char*数组 string类
- 《ACM程序设计》-Problem-Y-输出描述字符串
- Android笔记:视频播放器播放本地视频和网络视频
- [算法作业][LeetCode] 133. Clone Graph
- 一根网线,楼上楼下各自独立一趟网线均连接一个路由器,都要实现对外提供wifi信号
- 系统时间