今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理。首先这个设计模式出来的时候先是静态代理模式,只有理解了静态代理模式,才能理解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静态代理和动态代理的更多相关文章

  1. 【Java】代处理?代理模式 - 静态代理,动态代理

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

  2. Java:静态代理 and 动态代理

    代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...

  3. Java基础-静态代理与动态代理比较

    JAVA的静态代理与动态代理比较 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类: 在程序运行时,运用反射机制动态创建 ...

  4. java中静态代理,动态代理知识的补充

    文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...

  5. java静态代理与动态代理简单分析

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...

  6. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  7. java中的静态代理和动态代理,入门整理

    静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...

  8. Java 静态代理与动态代理

    代理模式 设想你的项目依赖第三方,但是你需要对其接口做一些数据检验.性能数据记录.异常处理等,合适的方法就是使用设计模式里的代理模式. 代理模式是常用的java设计模式,代理类与委托类有同样的接口,代 ...

  9. java之静态代理和动态代理

    我们以几个问题,来开始我们今天的学习,如果下面几个问题,你都能说出个一二,那么恭喜你,你已经掌握了这方面的知识.1,什么是代理模式?2,Java中,静态代理与动态代理的区别?3,Spring使用的是J ...

随机推荐

  1. bootstrap-wysiwyg 结合 base64 解码 .net bbs 图片操作类 (三) 图片裁剪

    官方的例子 是 长方形的. 我这里 用于 正方形的头像 所以  做如下  修改 #preview-pane .preview-container { width: 73px; height: 73px ...

  2. A WebBrowser Toy

    原文:A WebBrowser Toy 记得上大学时,某老师为了防止学生上课不听讲,只准学生在课堂上看他放映的PPT,不准学生拷贝,而考试的内容恰恰是PPT上的内容,于是一个同学来找我,我就用VB写了 ...

  3. HDU 1501 Zipper(DP,DFS)

    意甲冠军  是否可以由串来推断a,b字符不改变其相对为了获取字符串的组合c 本题有两种解法  DP或者DFS 考虑DP  令d[i][j]表示是否能有a的前i个字符和b的前j个字符组合得到c的前i+j ...

  4. 通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...

    原文:[原创]通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 'incorrect string value: '\xF0... 这篇blog重点在解决问题,如果你对 ...

  5. APP-随身听

    简单到复杂听你的专属音响界,听金融.听物业,听新闻和其他节目专辑,简要介绍了新的音频应用,给你不一样的聆听体验.还记得老歌做?这里有.您留声机的一部分!很简单的音频应用,随时随地与此应用程序来听你的私 ...

  6. PE文件结构(五岁以下儿童)基地搬迁

    PE文件结构(五岁以下儿童) 參考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 基址重定位 链接器生成一个PE文件时,它会如果程序被装入时使用的默认ImageBase基地址(VC默认 ...

  7. Redis查看帮助文档

    Redis查看帮助文档的方式,目前我用到的主要有两种: 1.访问官方文档: Redis文档 2.在redis-cli中通过命令查看,输入"?"或者"help"回 ...

  8. cocos2dx对于强大的RichText控制

    最近准备做一个聊天系统,开始准备使用cocos2dx的UIRichText控制显示屏聊天,在使用中发现的结果,cocos2dx的RichText很有限.全然不具备实现聊天的功能.仅仅实现了增加文本.图 ...

  9. PLSQL导入/导出数据方法

    PLSQL导入/导出数据方法 PLSQL导入/导出数据方法 以前导数据库信息的时候,总是会先开启sql窗口,把自己手写的建表文件复制进去,然后再导入数据信息. 今天突然懒得去找以前的建表文件,而想用S ...

  10. MVC 控制器激活

    MVC 控制器激活 ASP.NET MVC 控制器激活(三) 前言 在上个篇幅中说到从控制器工厂的GetControllerInstance()方法来执行控制器的注入,本篇要讲是在GetControl ...