Java动态代理
来源:互联网 发布:北京淘宝美工培训2ds 编辑:程序博客网 时间:2024/05/16 13:03
1、什么叫动态代理
“所谓运行时对类进行修改,打个比方来说,我写了一个HelloWorld的类,其中有两个方法:sayHello()和sayHelloToPHP(),
然后这个类运行起来了,我们希望在运行的时候可以修改这类:
1、加一个新方法sayHelloToPython();
2、现在的sayHello()方法里加一点新东西;
3、把sayHelloToPHP()这个方法删除;
2、为什么要用动态代理
因为会有这样的需求:
在某些函数调用前后加上日志记录
给某些函数加上事务的支持
给某些函数加上权限控制 等等
这些需求挺通用的,如果在每个函数中都实现一遍,那重复代码就太多了。 更要命的是有时候代码是别人写的,你只有class 文件,怎么修改? 怎么加上这些功能?所以就要用到动态代理。
3、动态代理怎么实现
由于Java的class在运行时就是不能被修改的,所以Java采取了一个折中的办法:
虽然不能修改现有的类,但是可以在运行时动态的创建新的类啊。让这个类作为HelloWorld的代理去做事情(加上日志功能),这个HelloWorld代理也实现了IHelloWorld接口。 所以在调用方看来,都是IHelloWorld接口, 并不会意识到其实底层已经改变了。
“大家能明白这个绿色的HelloWorld代理,但是你这个类怎么可能知道把Logger的方法加到什么地方呢?”
我们需要写一个类来告诉我们具体把Logger的代码加到什么地方, 这个类必须实现帝国定义的InvocationHandler接口,该接口中有个叫做invoke的方法就是他们写扩展代码的地方。 比如这个LoggerHandler:
无非就是在调用真正的方法之前先调用Logger.startLog(), 在调用之后在调用Logger.end(), 这就是对方法进行拦截了。
其实这个LoggerHandler 充当了一个中间层, 我们自动化生成的类$HelloWorld100会调用它,把sayHello这样的方法调用传递给他 (上图中的method变量),于是sayHello()方法就被添加上了Logger的startLog()和endLog()方法。
这个Handler不仅仅能作用于IHelloWorld 这个接口和 HelloWorld这个类,陛下请看,那个target 是个Object, 这就意味着任何类的实例都可以, 当然我们会要求这些类必须得实现接口。 臣民们使用LoggerHandler的时候是这样的:
输出: Start Logging
Hello World
End Logging
如果想对另外一个接口ICalculator和类Calcualtor做代理, 也可以复用这个LoggerHandler的类:
折腾了变天,原来魔法是在Proxy.newProxyInstance(….) 这里,就是动态地生成了一个类嘛, 这个类对臣民们来说是动态生成的, 也是看不到源码的。
我就是在运行时,在内存中生成了一个新的类,这个类在调用sayHello() 或者add()方法的时候, 其实调用的是LoggerHanlder的invoke 方法, 而那个invoke就会拦截真正的方法调用,添加日志功能了!
- Java 代理,动态代理
- [Java] Java 动态代理
- java代理及动态代理
- java代理模式--动态代理
- Java静态代理、动态代理
- Java 代理之 动态代理
- Java 代理与动态代理
- java静态代理,动态代理
- 代理模式&java动态代理
- Java代理与动态代理
- Java静态代理动态代理
- JAVA代理模式--动态代理
- java 代理和动态代理
- JAVA动态代理 代理模式
- Java动态代理--jdk代理
- Java动态代理--cglib代理
- Java 代理与动态代理
- java代理模式-动态代理
- MySql存储过程语法及事例
- 想要写出高性能sql语句,你得记住这些
- 排序 9
- _OBJC_CLASS_$_某文件名", referenced from:的问题
- form提交的错觉
- Java动态代理
- mysql用户与权限
- Unity 滑动事件6个方向的实现
- HDU
- CentOS7学习(1)
- [POJ2151]check the difficulty-概率DP
- 算法(二)
- 斯坦福大学CS231课程笔记1
- 安卓逆向环境搭建,SDK manager闪退问题