没事的时候翻看lang.reflect包下的代码,发现有两部分内容:涉及反射和动态代理。
很多地方都可以看到动态代理的影子,只是一直没仔细看下。
在学习之前,先提出几个问题,带着问题来看代码:
1.什么是动态代理?
2.为什么使用动态代理?
3.使用它有哪些好处?
4.哪些地方需要动态代理?
--------------------分隔线-----------------------------
和动态代理有关的有两个类
1.interface InvocationHandler
Object invoke(Object proxy, Method method, Object[] args)
只这一个方法,后面再说
2.class Proxy
真正表示动态代理的类,提供两个静态方法:
Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,
用来冒充真实的对象。
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法,
invoke方法就是我们用来做N多事情的地方 -_-。
--------------------分隔线-----------------------------
看完上面的代码,大致明白动态代理的含义:
A接口有c方法,类B实现A接口,原本应该是执行B类中的c方法,可现在不这样做;
我声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口,
对外界来说B'应该也有c方法,可当真正调用它的时候,
它会去执行与它关联InvocationHandler的invoke()方法,
在这个方法里面你可以做很多事情。这样,这个请求就被“代理”到其它地方去了。
下面是根据我的理解画的一个说明图
--------------------分隔线-----------------------------
引用网上的一个例子来说明问题(有部分改动,转载自:http://callan.iteye.com/blog/161806)
真实的接口:
- public interface Hello {
- void sayHello(String to);
- void print(String p);
- }
它的真实实现类:
- public class HelloImpl implements Hello {
- public void sayHello(String to) {
- System.out.println("Say hello to " + to);
- }
- public void print(String s) {
- System.out.println("print : " + s);
- }
- }
在这里生成与代理类相关联的InvocationHandler对象
- public class LogHandler implements InvocationHandler {
- private Object dele;
- public LogHandler(Object obj) {
- this.dele = obj;
- }
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- doBefore();
- //在这里完全可以把下面这句注释掉,而做一些其它的事情
- Object result = method.invoke(dele, args);
- after();
- return result;
- }
- private void doBefore() {
- System.out.println("before....");
- }
- private void after() {
- System.out.println("after....");
- }
- }
最后是测试类:
- public class ProxyTest {
- public static void main(String[] args) {
- HelloImpl impl = new HelloImpl();
- LogHandler handler = new LogHandler(impl);
- //这里把handler与impl新生成的代理类相关联
- Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);
- //这里无论访问哪个方法,都是会把请求转发到handler.invoke
- hello.print("All the test");
- hello.sayHello("Denny");
- }
- }
这里是输出结果:
- before....
- print : All the test
- after....
- before....
- Say hello to Denny
- after....
--------------------分隔线-----------------------------
最后试着来回答之前提出的问题:
1.什么是动态代理?
一种用于转发请求,进行特殊处理的机制,“动态”应该指的是“运行期”。
2.为什么使用动态代理?
可以对请求进行任何处理(如事务,日志等,这都是网上说的,我当然可以做任何处理)
3.使用它有哪些好处?
如上
4.哪些地方需要动态代理?
不允许直接访问某些类;对访问要做特殊处理等,我只能想到这些。
--------------------分隔线-----------------------------
其它一些想法:
1.如果想声明产生B类的代理类,那个B类必须要实现接口,如果没有接口,
代理类就不能伪装成B类的“兄弟”,也就没有存在的意思,
其实也可以伪装成B类的“孩子”,对外他们有共同的接口,可以这样做吧?
2.当请求代理类的方法时,这个请求会被转到执行与代理类关联InvocationHandler
的invoke方法。那InvocationHandler到底是什么?对它的理解可以是这样:
它用来处理方法的调用,实现类也有同样的意义;与代理类对象相关联则表示,
它就是负责处理代理类应该有的动作,把所有的方法请求分发到invoke这个方法上。
--------------------分隔线-----------------------------
学习后总结,既可以全面地观察分析,又能加深印象。
如果我的理解有误,别人的指证会对我产生积极影响。
如果我的理解正确,帮助其它人理解是我的荣幸。
初学者,请多多指教。
原文地址:http://langyu.iteye.com/blog/410071
相关推荐
2009-02-24 08:42 165165 37065 常见的专业问题解决办法\Java核心技术学习笔记--异常和调试_Believe ┭┮ YourSelf.mht 2009-03-20 16:36 142683 39110 常见的专业问题解决办法\JR - 专题论坛问题 - eclipse??如何...
3 Android SqliteManager 源码.zip
内容概要:本文详细介绍了基于S7-200 PLC的煤矿排水系统智能控制方案,重点讨论了三台水泵(两台工作水泵和一台备用水泵)的联动与备援策略。系统通过超声波液位传感器实时监测水位,根据不同水位情况自动控制水泵的启停。具体而言,水位低时不启动水泵,水位介于中水位和高水位之间时启动1号水泵,水位超过高水位则启动1号和2号水泵共同工作。若1号或2号水泵出现故障,系统会自动启用3号备用水泵。此外,MCGS6.2组态画面用于实时监控水位和水泵状态,帮助操作员及时应对异常情况,确保矿井安全。 适合人群:从事煤矿自动化控制领域的技术人员、矿业工程管理人员及相关研究人员。 使用场景及目标:适用于需要提高煤矿排水系统自动化水平的场合,旨在提升矿井排水效率和安全性,减少人工干预,确保矿井生产安全。 其他说明:文中提到的技术方案不仅提高了排水系统的可靠性,还为未来的智能化矿山建设提供了有益借鉴。
scratch少儿编程逻辑思维游戏源码-灌篮之王.zip
scratch少儿编程逻辑思维游戏源码-飞翔马里奥(2).zip
scratch少儿编程逻辑思维游戏源码-火柴人大战 中世纪战争.zip
scratch少儿编程逻辑思维游戏源码-几何冲刺(2).zip
南京证券-低轨卫星互联网启动,天地一体通信迈向6G
nginx-1.20.1
sshpass-1.06-8.ky10.aarch
少儿编程scratch项目源代码文件案例素材-我的世界2D(更新北极).zip
通信行业专题研究:车载全息数字人——AI+Agent新场景,全息投影新方向-20231121-国盛证券-13页
内容概要:本文详细介绍了利用西门子S7-200 PLC和组态王软件构建的邮件分拣系统的具体设计方案和技术细节。首先,文中阐述了硬件部分的设计,包括光电传感器、传送带电机以及分拣机械臂的连接方式,特别是旋转编码器用于精确测量包裹位移的技术要点。接着,展示了PLC编程中的关键代码段,如初始化分拣计数器、读取编码器数据并进行位置跟踪等。然后,描述了组态王作为上位机软件的作用,它不仅提供了直观的人机交互界面,还允许通过简单的下拉菜单选择不同的分拣规则(按省份、按重量或加急件)。此外,针对可能出现的通信问题提出了有效的解决方案,比如采用心跳包机制确保稳定的数据传输,并解决了因电磁干扰导致的问题。最后,分享了一些现场调试的经验教训,例如为减少编码器安装误差对分拣精度的影响而引入的位移补偿算法。 适合人群:从事自动化控制领域的工程师或者对此感兴趣的初学者。 使用场景及目标:适用于需要提高邮件或其他物品自动分拣效率的企业或机构,旨在降低人工成本、提升工作效率和准确性。 其他说明:文中提到的实际案例表明,经过优化后的系统能够显著改善分拣性能,将分拣错误率大幅降至0.3%,并且日均处理量可达2万件包裹。
scratch少儿编程逻辑思维游戏源码-机械汽车.zip
内容概要:本文详细探讨了在连续介质中利用束缚态驱动设计并实现具有最大和可调谐手征光学响应的平面手征超表面的方法。文中首先介绍了comsol三次谐波和本征手性BIC(束缚态诱导的透明)两种重要光学现象,随后阐述了具体的手征超表面结构设计,包括远场偏振图、手性透射曲线、二维能带图、Q因子图和电场图的分析。最后,通过大子刊nc复现实验验证了设计方案的有效性,并对未来的研究方向进行了展望。 适合人群:从事光学研究的专业人士、高校物理系师生、对光与物质相互作用感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解手征超表面设计原理及其光学响应机制的研究人员,旨在推动新型光学器件的研发和技术进步。 其他说明:本文不仅展示了理论分析和模拟计算,还通过实验证明了设计方法的可行性,为后续研究奠定了坚实的基础。
少儿编程scratch项目源代码文件案例素材-位图冒险.zip
少儿编程scratch项目源代码文件案例素材-校园困境2.zip
少儿编程scratch项目源代码文件案例素材-兔子吃萝卜.zip
scratch少儿编程逻辑思维游戏源码-海洋战争.zip
房地产 -前策标准化-沪浙一部.pptx