从Proxy.newProxyInstance说起

原创 2007年10月11日 22:19:00
  最近一直在看java的设计模式 ,感觉印象最深刻的就是"面向接口编程",在java中,尽量多定义接口,因为设计的最重要的目的就是应对各种变化,而接口本身就是一种变化着的Class的直接反映,通过实现特定接口的各种具体类,达到应对变化的目的,下面以Proxy模式为例:
Proxy的模式最主要的目的,原有的类对象由于某种原因不能访问,需要通过一个新的类来间接地去实现,这个新的类就称为代理类,举个例子说明,老王买/卖鱼的例子
public class SellFisher ...{
    
public int sellFish() ...{
        System.out.println(
"my fish is delicious!!");
        
return 10;
    }

}
这是一个具体的卖鱼类,表示鱼10元/斤,如果这个类被用到系统中的时候,系统应对变化的灵活性就会大打折扣,请看如下:
public class SellFishSystem ...{
    
private SellFisher sellfish;
                     
//...
    public void sellFish() ...{
        sellfish.sellFish();
    }

}
如果以后鱼的价格变化,或者具体的卖鱼方法发生变化,就必须修改已经有的SellFisher的sellFish()的代码,这个情况
使得系统的可扩展性降低,我们肯定会想到解决方案了,定义一个接口,请看代码:
interface SellFisher ...{
    
int sellFish();
}

public class SellFishSystem ...{
    
private SellFisher sellfish;
    
public void sellFish() ...{
        sellfish.sellFish();
    }

}
我们所做的变化,只是把SellFisher从Class提升到Interface,这个时候好处自然很明显了,这个SellFisher本身就代表
了一种不确定,变化.大家在做开发的时候,阅读源代码的时候,肯定遇到过这种情况,总是跟踪类的对象看代码实现,如果发现了接口变量,就会比较郁闷,得了解它的具体实现类是什么,这个具体实现类的变化通常就可以应对需求的变化,系以及系统扩展.请看上例子,如果鱼的价格变化,或者具体的卖鱼方法发生变化,我们只需要新增加SellFisher的实现,
而不必修改已有的代码,对此我的理解是对系统来说,新增加一个类的代码风险要大大低于对已有类的代码的修改.我觉得这个也是设计模式的立足点吧(如果你喜欢修改已有代码,那么设计模式就没有多大意义了)
言归正传,有了上面的知识准备,我们接上面的例子来解释Proxy的模式就简单多了,比如现在鱼的价格变化,卖鱼的提示也发生变化了,我们需要一个新的Proxy类来实现
interface SellFisher {
    
int sellFish();
}

public class ConcreteSellFisher implements SellFisher {

    
public int sellFish() {
         System.out.println(
"my fish is delicious!!");
         
return 10;
    }

}

public class ProxySellFisher implements SellFisher {

    
private SellFisher sell;
    
public ProxySellFisher(SellFisher sell) {
        
this.sell = sell;
    }
    
public int sellFish() {
        System.out.println(
"the fish price higher");
        
return sell.sellFish()+10;
    }

}
看上面,这个是Proxy模式的代码例子实现,我们现在在SellFishSystem 使用ProxySellFisher来卖鱼了,由ProxySellFisher再调用原来的ConcreteSellFisher类.具体的一些特征总结为:
1.有个代理类Proxy(和原来的实现类继承同一接口),该类里引用了原来的具体功能实现类(这里是ConcreteSellFisher)
2.重写实现方法,加一些新的变化的元素(比如鱼的价格上涨)
JDK里的Proxy类也实现了这个模式,只不过它叫动态代理,因为它的代理类变成了InvocationHandler了,执行的方法
是invoke了,从而变得更加灵活了,请看代码
public class ProxySellFisher implements InvocationHandler {

    
private SellFisher sell;
    
public ProxySellFisher(SellFisher sell) {
        
this.sell = sell;
    }
    
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
        System.out.println(
"the fish price higher");
        
return (Integer)method.invoke(sell, args)+10;
    }

}


public class ClientTest {
    
public static void main(String args[]) {
        SellFisher s 
= new ConcreteSellFisher();
        InvocationHandler p 
= new ProxySellFisher(s);
        Object obj 
= Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(), p);
        ((SellFisher)obj).sellFish();
    }
}
请注意,invoke(Object obj,Method method,Object[] args),这里的第一个参数obj其实可以看作没有用处的,不知道jdk为什么要把它也当作一个参数放这里,methd.invoke()方法,需要把原来的具体实现类作为参数传递进去,method.invoke(obj,args)相当于obj.method(args)
总结,从设计模式的角度讲,大家以后编程中,尽量要面向接口,更通俗一点就是,一个类中使用的别的对象成员变量,最好定义成接口的变量而不是实际实现类的变量

代理模式深入学习(一)——动态代理的实现及解析

关于代理模式,就在不久的前的几天,大概是8月17日左右,我带领的小组还曾经被分配任务去给大家讲解代理模式,总共给了两天时间,但是,依然,我们有很多问题没有解决。比如动态代理的一些问题等等。在经历了DR...
  • wangyy130
  • wangyy130
  • 2015年09月30日 15:56
  • 1848

从代理模式再出发!Proxy.newProxyInstance的秘密

上一节简单介绍了一下ClassLoader,我们知道,在我们用Proxy.newProxyInstance实现动态代理的时候,有三个参数,第一个便是classloader,这一篇文章就是简单看一下Pr...
  • lovejj1994
  • lovejj1994
  • 2017年09月24日 21:43
  • 757

动态代理(3)- newProxyInstance()实现原理

对于newProxyInstance方法我们先将一下整个实现的思路。       总体思路就是他通过字符串化产生一个新的java类,再动态编译返回对象。注意是动态编译。       简单来...
  • weidea
  • weidea
  • 2015年01月31日 22:41
  • 1884

jdk动态代理实现原理

java中可以通过jdk提供的 Proxy.newProxyInstance静态方法来创建动态代理对象,下面先来看看这个方法的实现 public static Object newProxyIns...
  • MoreeVan
  • MoreeVan
  • 2013年09月13日 15:14
  • 12872

java中代理模式以及new和newInatance()的区别

在java开发过程中经常使用到代理模式,其中代理模式分为静态代理和动态代理。 代理模式主要通过代理来实现对外功能,但是代理类本身并不实现功能,主要通过调用被代理的对象来实现功能。 静态代理:已经写...
  • lnjphjh
  • lnjphjh
  • 2015年09月26日 18:25
  • 740

深入理解Java Proxy机制

     动态代理其实就是java.lang.reflect.Proxy类动态的根据您指定的所有接口生成一个class byte,该class会继承Proxy类,并实现所有你指定的接口(您在参数中传入...
  • rokii
  • rokii
  • 2009年04月03日 12:34
  • 58720

java动态代理原理及解析

java动态代理, jdk反射与代理模式
  • Scplove
  • Scplove
  • 2016年09月06日 17:25
  • 36640

解决Proxy.newProxyInstance创建动态代理导致类型转换错误的问题

在使用Proxy.newProxyInstance创建动态代理时,有时会导致类型转换错误。 package cn.itcast.demo; import java.io.InputStream; ...
  • wliang11
  • wliang11
  • 2013年11月28日 22:19
  • 1613

(二)代理模式详解(包含原理详解)

作者:zuoxiaolong(左潇龙) 出处:博客园左潇龙的技术博客--http://www.cnblogs.com/zuoxiaolong                我特意将...
  • fyj459008841
  • fyj459008841
  • 2016年05月09日 13:46
  • 609

设计模式——代理模式实现与原理分析

代理模式也称为委托模式,也是极为重要的设计模式之一。代理在我们日常生活中其实很常见,对于程序员来说最常接触的莫过于使用代理上网,连接上代理服务器地址,就可以轻松畅游全世界的网络;让同事帮忙带饭也是一种...
  • ylyg050518
  • ylyg050518
  • 2016年11月12日 18:50
  • 1336
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:从Proxy.newProxyInstance说起
举报原因:
原因补充:

(最多只允许输入30个字)