`
小牛犊
  • 浏览: 96971 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Proxy.newProxyInstance()

    博客分类:
  • Java
阅读更多

from:http://blog.csdn.net/dan_xp/archive/2007/10/11/1820852.aspx

 

 最近一直在看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)
总结,从设计模式的角度讲,大家以后编程中,尽量要面向接口,更通俗一点就是,一个类中使用的别的对象成员变量,最好定义成接口的变量而不是实际实现类的变量
分享到:
评论
3 楼 IO_oI 2012-09-04  
引用
一个类中使用的别的对象成员变量,最好定义成接口的变量而不是实际实现类的变量

但是接口内定义的变量不都是默认被public static final修饰吗?
2 楼 love_reboot 2011-03-22  
一个类中使用的别的对象成员变量,最好定义成接口的变量而不是实际实现类的变量弱弱的问一下,接口能定义变量吗?
1 楼 love_seam 2010-07-19  
折腾一大圈,跟下面的代码有什么区别?
        SellFisher s = SellFisherFactory.getSellFisher(...);//这里根据context返回想要的实现。
        s.sellFish()...


简单的代码整复杂了,说起来为了美观,结果难以维护,看起来很晦涩。光Proxy.newProxyInstance这个东西就能把人折磨死。

相关推荐

    用newProxyInstance方式和getProxyClass方式动态代理.zip

    Object proxy = Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); ``` 其中,`MyInvocationHandler`是你实现的`InvocationHandler`,`target`是你...

    proxy.rar java三种代理模式源码

    在"InterfaceProxy"目录中,你可以看到如何利用`Proxy.newProxyInstance()`方法创建接口的代理对象,并通过实现`InvocationHandler`接口的`invoke()`方法来控制代理对象的行为。这种方式比静态代理更灵活,因为不...

    java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar

    * 动态代理中的静态方法:java.lang.reflect.Proxy.newProxyInstance (ClassLoader(类加载器),interface(接口),handler(监听处理器)) * * 代码示例:《帮爸爸买菜》 * 1.Father: 被代理类,必须需要实现接口 ...

    反射与动态代理Reflection&DynamicProxy.zip

    通过`Proxy.newProxyInstance()`方法,我们可以创建一个实现了特定接口的代理对象。 2. **InvocationHandler接口**:每个代理对象都关联一个`InvocationHandler`,它定义了方法调用的处理逻辑。当调用代理对象的方法...

    Java 动态代理Proxy应用和底层源码分析.pdf

    接着,我们创建了一个`MyInterface`接口的匿名实现`myObject`,并通过`Proxy.newProxyInstance`方法创建了一个代理对象`proxy`。最后,我们通过调用`proxy.doSomething()`来测试我们的动态代理是否按预期工作。 ###...

    代理模式 proxy-learn.rar

    Service proxyService = (Service) Proxy.newProxyInstance( Service.class.getClassLoader(), new Class[]{Service.class}, new MyInvocationHandler(realService) ); ``` 4. **调用方法**:通过代理对象调用`...

    深入理解JavaProxy机制.doc

    通过`Proxy.newProxyInstance()`方法,我们创建了一个代理对象`bp`,这个对象实现了`BusinessProcessor`接口,但其行为由`handler`控制。当我们调用`bp.processBusiness()`时,实际上会执行`...

    Aop jdk proxy实现小例子

    Service proxyService = (Service) Proxy.newProxyInstance( Service.class.getClassLoader(), new Class[]{Service.class}, new MyInvocationHandler(service) ); proxyService.doSomething(); } } ``` 在...

    java Proxy 动态代理

    - `Proxy.newProxyInstance()`是Proxy类的核心方法,用于创建代理对象。它需要三个参数:一个ClassLoader对象,一个接口数组,以及一个InvocationHandler实例。ClassLoader用于加载代理对象的类,接口数组指定了...

    Java动态代理Proxy和cglib

    MyInterface proxy = (MyInterface) Proxy.newProxyInstance( MyInterface.class.getClassLoader(), new Class[]{MyInterface.class}, new MyInvocationHandler(target) ); proxy.doSomething(); } } ``` 在...

    深入理解Java Proxy机制.doc

    通过`Proxy.newProxyInstance()`方法,我们可以动态地创建这样的代理对象。 3. **InvocationHandler接口**: - `InvocationHandler`接口定义了一个方法`invoke()`. 当通过代理对象调用任何接口方法时,实际的调用...

    java 代理简单代码demo

    MyInterface proxy = (MyInterface) Proxy.newProxyInstance( MyInterface.class.getClassLoader(), new Class[]{MyInterface.class}, new MyInvocationHandler(target) ); proxy.doSomething(); } } ``` ...

    JAVA动态代理

    MyInterface proxy = (MyInterface) Proxy.newProxyInstance( MyInterface.class.getClassLoader(), new Class[]{MyInterface.class}, new MyInvocationHandler(target) ); proxy.doSomething(); // 会打印出...

    Java动态代理实现 Proxy InvocationHandler

    - `Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)`:这个方法用于创建一个动态代理类的实例。参数分别表示类加载器、目标类实现的接口列表和一个`InvocationHandler`对象。...

    Java代理实战Demo

    2. 使用Proxy.newProxyInstance()静态方法,传入目标对象的类加载器、目标对象所实现的接口列表以及刚才创建的InvocationHandler实例,生成代理对象。 3. 通过代理对象调用方法,实际调用会转到之前定义的...

    java-用Java动态代理实现AOP.pdf

    BusinessInterface proxy = (BusinessInterface) Proxy.newProxyInstance( BusinessInterface.class.getClassLoader(), new Class[]{BusinessInterface.class}, new LogHandler(business) ); proxy....

    动态代理接口并注册到spring容器

    现在,我们可以使用`Proxy.newProxyInstance()`方法创建代理对象: ```java MyService myServiceProxy = (MyService) Proxy.newProxyInstance( MyService.class.getClassLoader(), new Class[]{MyService.class},...

    java proxy

    MyService proxyService = (MyService) Proxy.newProxyInstance( MyService.class.getClassLoader(), new Class[]{MyService.class}, new MyInvocationHandler(myService) ); proxyService.doSomething(); } ...

    动态代理例子

    - 最后,使用Proxy.newProxyInstance()创建代理对象,传入接口类型、类加载器和你的InvocationHandler实现。 例如,我们可以定义一个名为`Service`的接口,包含一些业务方法,然后创建一个实现`InvocationHandler`...

Global site tag (gtag.js) - Google Analytics