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 ...
随机推荐
- 微信公众平台接口,asp.net实现
原文:微信公众平台接口,asp.net实现 我为自己的笑话网开发了一个微信公众平台的接口,在这里分享给大家,希望能对朋友们有帮助,如果有什么地方写的不好,好请大家指点! 首先是要进行认证,认证的时候, ...
- GhostDoc的使用
原文:GhostDoc的使用 一.简介 GhostDoc是Visual Studio的一个免费插件,可以为开发人员自动生成XML格式的注释文档. 二.下载 需要的朋友可以去这里下载,填个Email地址 ...
- Eclipse生成jsp 如何将GB18030 改成默认UTF-8
前两天面试被问到了struts的问题,好久没用了准备复习下,用eclipse创建一个maven项目的时候发现创建的jsp文件都是GB18030编码的,如何更改为UTF-8呢,其实很简单,给各位分享一下 ...
- 在ASP.NET应用中执行后台任务
在ASP.NET应用中执行后台任务 昨天下午,在微软的MVP 2015社区大讲堂上给大家分享了一个题目:在ASP.NET应用中执行后台任务.这是一点都不高大上,并且还有点土气的技术分享.不过我相信很多 ...
- POJ 2553 The Bottom of a Graph (强连通分量)
题目地址:POJ 2553 题目意思不好理解.题意是:G图中从v可达的全部点w,也都能够达到v,这种v称为sink.然后升序输出全部的sink. 对于一个强连通分量来说,全部的点都符合这一条件,可是假 ...
- Scala Sublime text 3 Build 编译
使用Sublime text 3编译Scala 在sublime工具栏中[tools]->[Build System]->[new Build System]添加如下文本 { " ...
- SQL点滴23—T-SQL中的除法
原文:SQL点滴23-T-SQL中的除法 在T-SQL中没有除法运算,但是在T-SQL中可以实现类似除法的操作Divide.一般除法操作的结果一个列来自于被除关系表,剩下的来自除关系表.这里举一个例子 ...
- 在weblogic11g发布该项目时遇到错误(不支持web-app_3_0)
problem: cvc-enumeration-valid: string value '3.0' is not a valid enumeration value for web-app-vers ...
- Python装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 ? 1 2 3 4 5 6 7 8 # -*- ...
- 自己写RTPserver——大约RTP协议
自己写RTPserver--大约RTP协议 本文将带领你一步一步地实现一个简单的手RTP变速器server,旨在了解RTP流媒体传输协议以及有关多媒体编解码器的一些知识. RTP协议的必备知识 要动手 ...