Java静态代理和动态代理
今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理。首先这个设计模式出来的时候先是静态代理模式,只有理解了静态代理模式,才能理解JDK提供的动态代理是怎么回事,首先介绍静态代理,如果有错误的地方请大家不要拍砖,请大家指正。
一,静态代理
第一种情况:假如我去租房,没有经过中介,直接找到了房屋的主人。这里抽象一下就是我直接访问了真实对象(房屋的主人),然后我把房屋给租了。
第二种情况:假如我去租房,需要经过中介,找到一家租房的中介公司,然后把房屋租了。这里抽象一下就是我访问了真实对象的代理对象(中介),这里的代理对象(中介)需要持有真实对象(房屋主人)才能把房屋租给我(因为中介手里没有房子,他肯定要有房屋真实主人的房子才行)。结构图如下:
大家一定要明白的是,代理对象(中介)一定要持有真实对象(房屋主人)才行。
下边是静态代理的代码实现:
首先代理对象和真实对象都需要实现同一个接口或继承抽象类,这个接口或者抽象类其实就是说我这里是租房屋的,不是租汽车的或别的东西,接口中定义一个quote(报价)方法。
public interface Subject {
/***
* 这个接口定义一个报价方法
*/
public String quote(); }
然后定义一个真实对象类,就是代表真实的房屋的主人,实现Subject接口,同时实现报价方法:
public class RealSubject implements Subject {
@Override
public String quote() {
return "房屋出租2000元一个月";
}
}
定义一个代理类,这个代理类一定持有真实对象的引用
public class ProxySubject implements Subject{
@Override
public String quote() {
//代理对象持有真实对象
Subject subject = new RealSubject();
//返回真实对象的报价多少钱
String quote = subject.quote();
//代理对象增加真实对象的报价
return quote.replace("2000", "3000");
}
}
编写我们的测试类,租房去找中介,然后查看房屋的报价是多少钱
public static void main(String[] args) {
/**
* 代理对象和真实对象都要实现同一个接口
*/
//直接访问真实对象
Subject subject = new RealSubject();
System.out.println(subject.quote()); //访问代理对象
subject = new ProxySubject();
System.out.println(subject.quote());
}
执行之后会发现中介把房屋的租金增加了,这就起到了代理的作用。这就是一个静态代理的小例子,静态代理主要注意两点:1,真实类和代理类都实现一个相同的接口;2,代理类持有真实类的对象的引用。按照租房的情况说明就是:中介和房租主人都必须是卖房子的,不能你去中介租房,结果给你返回一个汽车的报价;中介必须有房屋主人的房子才能租给你,如果中介手中没有房子,只是一个空壳子,也没有办法把房子租给你。
静态代理的一个不好的地方是如果接口里增加了一个方法,那么真实类和代理类都必须实现相应的方法,增加了代码的复杂程度。还有就是如果代理类没有实现接口怎么办(解决办法自行百度吧 ^_^)
二,动态代理
JDK提供了一个java.lang.reflect.Proxy对象,可以用来对真实类实现动态代理,在运行时通过反射增强真实类。我们这里给Subject接口增加一个方法 getHouseAddress(得到房子的地址),然后真实类实现这个方法,返回"房屋的地址在地球";代码如下:
public class RealSubjectHome implements Subject{ @Override
public String quote() {
return "房屋出租2000元";
} @Override
public String getHouseAddress() {
return "房屋的地址在地球";
}
}
这里我们看一下代理类的实现(主要的解释都在注释中):
public final class DynamicProxy implements InvocationHandler{ //代理对象是要持有真实对象
private Object RealObject; public Object createSubject(Object RealObject){
/**
* 参数含义:
* classloader 是代理的类加载器
* interface 就是代理类实现的接口,因为代理类需要和真实对象实现相同的接口,所以返回的就是真实类的接口
* InvocationHandler 调用真实类的处理函数,代理类需要对真实对象做一些处理
* 返回值 返回一个真实类的代理对象
*
*/
this.RealObject = RealObject;
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
this.RealObject.getClass().getInterfaces(), //这里是真实对象实现的接口,代理对象也要实现相同的接口
this);
}
/**
* 参数:
* proxy 就是代理类的对象
* method 就是需要调用的实现接口中的方法
* args 方法中的参数
* 返回值 返回代理类调用实现接口的方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//调用真实对象中的方法,获取返回值
if(method.getName().equals("quote")){
String returnValue = (String) method.invoke(this.RealObject, args);
returnValue = returnValue.replace("2000", "3000");
return returnValue;
}
//其他不需要代理类修改的方法
return method.invoke(this.RealObject, args);
}
}
其中Proxy.newProxyInstance方法返回一个代理对象,其中的第三个参数是实现InvocationHandler的接口,当调用代理对象的方法的时候,会调用InvocationHandler接口中的invoke方法用来对真实对象的方法增强,我们在invoke方法中只修改了获得房屋报价的内容。对获得房屋地址方法没有进行更改,直接调用真实对象的方法就行了。解释一下就是中介会把房屋的出租价格提高,但是房屋的地址不能修改吧,所以动态代理可以很好的控制需要增强的方法。
看一下我们的测试类:
public static void main(String[] args) { //找代理出租房屋
RealSubjectHome subjecthome = new RealSubjectHome();
DynamicProxy proxy = new DynamicProxy();
Subject subject = (Subject) proxy.createSubject(subjecthome);
//得到房屋的报价信息
System.out.println(subject.quote());
//得到房屋的地址
System.out.println(subject.getHouseAddress());
}
使用动态代理编写代理类的时候,其实并不难,只要注意两点就行了:1,代理类持有真实类的引用 2,代理类和真实类实现同一个接口。然后要多proxy类的newProxyInstance的参数含义理解,对InvocationHandler中的invoke方法的参数理解,就可以了。
动态代理的思想在框架中使用的很多,其实使用jdk提供的动态代理的实现并不是很多,都是使用三方的实现,例如CGLIB,直接对类的字节码文件进行增强。静态代理和动态代理的实现就先这样,如果叙述中有错误,请指明。
Java静态代理和动态代理的更多相关文章
- 【Java】代处理?代理模式 - 静态代理,动态代理
>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...
- Java:静态代理 and 动态代理
代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...
- Java基础-静态代理与动态代理比较
JAVA的静态代理与动态代理比较 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类: 在程序运行时,运用反射机制动态创建 ...
- java中静态代理,动态代理知识的补充
文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...
- java静态代理与动态代理简单分析
原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...
- 黑马程序员:Java基础总结----静态代理模式&动态代理
黑马程序员:Java基础总结 静态代理模式&动态代理 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public class Ts { ...
- java中的静态代理和动态代理,入门整理
静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...
- Java 静态代理与动态代理
代理模式 设想你的项目依赖第三方,但是你需要对其接口做一些数据检验.性能数据记录.异常处理等,合适的方法就是使用设计模式里的代理模式. 代理模式是常用的java设计模式,代理类与委托类有同样的接口,代 ...
- java之静态代理和动态代理
我们以几个问题,来开始我们今天的学习,如果下面几个问题,你都能说出个一二,那么恭喜你,你已经掌握了这方面的知识.1,什么是代理模式?2,Java中,静态代理与动态代理的区别?3,Spring使用的是J ...
随机推荐
- Java利用jcifs集成AD域用户认证
近期一段时间发现AD这东西老火了,尤其是涉及到安全这一方面的,所以AD域用户认证成了如今网络安全方面的产品必备!这里就简单的分享一下,Java通过jcifs集成AD域用户实现认证,以实现网络安全! 我 ...
- C# winform调用WebBrowser经典怪问题总结
原文:C# winform调用WebBrowser经典怪问题总结 最近一直研究网页数据采集,单单采集数据,其实HtmlAgilityPack就足够了. 对HtmlAgilityPack感兴趣的可以到这 ...
- IT见解
IT见解 北京海淀区 2014-10-18 张俊浩 *域名的市值在走低,因其功能被新浪.腾讯微博.微信大V这种账号所代替 *小米将自己定位为互联网公司,而不是手机公司 *手机不远的未来会成为公共 ...
- sax(用于处理XML事件驱动的推模型)解析例子
SAX解析 Java程序如下: import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; impor ...
- hdu149850 years, 50 colors (多个最小顶点覆盖)
50 years, 50 colors Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- C语言连接Oracle
原文:C语言连接Oracle 最近在搞C语言连接Oracle.DB2数据库,现把C连接Oracle的文章总结下: 用C语言连接ORACLE数据库.有两个思路和目的 思路一)本地环境:UBUNTU 7. ...
- 个人学习JQ插件编写成果:little酷炫的图片滑动切换效果
工作一个多月了,好久没来冒冒泡了,看了@wayong的JQ插件教程,自己编写了一个模仿拉勾网首页广告栏滑动特效的JQ插件,现在跟朋友们分享分享! 先上demo链接:http://runjs.cn/de ...
- UUShutdown关机工具 - 给 Windows8.1Metro 开始屏幕添加 关机重启按钮
UUShutdown,给开始屏幕(开始菜单)添加重启关机等按钮 如图: 安装完成之后找到开始菜单程序文件夹中的快捷方式,附加到开始屏幕即可. 2.0加入主程序界面,支持换肤和定时: 看见的需要那就拿去 ...
- 算法课上机实验(一个简单的GUI排序算法比较程序)
(在家里的电脑上Linux Deepin截的图,屏幕大一点的话,deepin用着还挺不错的说) 这个应该是大二的算法课程上机实验时做的一个小程序,也是我的第一个GUI小程序,实现什么的都记不清了,只记 ...
- 小公司免费的ERP软件
http://www.2bizbox.cn/ https://www.odoo.com/