`

设计模式之--动态代理

阅读更多
动态代理类是一个在运行时由开发人员所指定的一列接口的实现。动态代理接口是一种由代理类实现的接口,并且是一个java.lang.reflect.Proxy类的实例。每一个代理实例都与一个调用处理器对象相联,这个调用处理器实现了java.lang.reflect.InvocationHandler接口。在代理实例上的一个方法调用是通过其中之一的代理接口被转发到与这个代理实例相联的调用处理的invoke方法上。一个java.lang.reflect.Method对象会决定那一个方法会被调用,一个类型为java.lang.Object的数组包含调用的参数。调用处理器会适当地解码方法的调用(encoded method invocation as appropriate),并且它(调用处理器)的返回结果被作为在代理实例上方法调用返回的结果而返回。

例如,我们已有和装饰器模式中一文中一样的接口IMyBusinessObject和业务类MyBusinessObject。现在当我们使用动态代理时,我必须编写一个调用处理器,因为java.lang.reflect.Proxy类将会用到它。

MyDebugInvocationHandler类看起来像下面那样:

Java代码
public class MyDebugInvocationHandler implements InvocationHandler {  
    private Object target ;  
      
    public void setTarget(Object target) {  
        this.target = target;  
    }  
 
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        System.out.println("Going to execute method :"+method.getName());  
        Object  retObject = method.invoke(target, args);  
        System.out.println("After execute method :"+method.getName());  
        return retObject;  
    }  
 


public class MyDebugInvocationHandler implements InvocationHandler {
    private Object target ;
   
public void setTarget(Object target) {
this.target = target;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
    System.out.println("Going to execute method :"+method.getName());
    Object  retObject = method.invoke(target, args);
    System.out.println("After execute method :"+method.getName());
return retObject;
}

} 在上面的例子中,invoke ()方法是很重要的,它是被java.lang.reflect.Proxy类所调用的。在这个方法里面,我们执行了一些额外的处理,然后转至真正的目标对象的处理(在这个例子中,是实例MyBusinessObject)。
因此我们的客户端应作如下编码:

Java代码
IMyBusinessObject bo = new MyBusinessObject();  
        MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler();  
        aMyDebugInvocationHandler.setTarget(bo);  
        IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy  
                .newProxyInstance(IMyBusinessObject.class.getClassLoader(),  
                        new Class[] { IMyBusinessObject.class },  
                        aMyDebugInvocationHandler);  
System.out.println(proxyObject.doExecute("Hello World"));  

IMyBusinessObject bo = new MyBusinessObject();
MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler();
aMyDebugInvocationHandler.setTarget(bo);
IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy
.newProxyInstance(IMyBusinessObject.class.getClassLoader(),
new Class[] { IMyBusinessObject.class },
aMyDebugInvocationHandler);
System.out.println(proxyObject.doExecute("Hello World"));




输出结果:

Java代码
Going to execute method :doExecute   
Here in MyBusinessObject doExecute: input :Hello World   
After execute method :doExecute   
Hello World  

Going to execute method :doExecute
Here in MyBusinessObject doExecute: input :Hello World
After execute method :doExecute
Hello World  在上面的代码中,我分别创建一个MyBusinessObject实例和一个MyDebugInvocationHandler实例。我们在MyDebugInvocationHandler中设定目标对象为MyBusinessObject。因此当invoke()方法被调用时,它能够把调求发向正确的目标。然后,我们使用java.lang.reflect.Proxy去创建一个IMyBusinessObject接口的代理对象。既然invoke()方法会处理java.lang.reflect.Mehtod类的生成并且其中没有特定的业务接口的方法,通常这些特定的业务接口的方法在每一个业务接口分别编写个业调用处理器是必须的,知道这一点是很重要的。还有,如果我们想实现一些横跨所有业务接口的横切面(cross-cutting aspect),我们不必实现在业务接口中定义的所有业务方法。例如,为了在我们的业务方法中实现安全性,我们仅仅只须在一个地方编写一个方法去实现安全逻辑,这个安全方法我们将以通用的方法编写。

如果我们想在链中增加多个处理器,我们必须创建另一个调用处理器。然后在新定义的处理器中的setTarget()中我们把它设定为链中的前一个代理对象,而不是设定为MyBusinessObject对象。另一个调用处理器代码如下:

Java代码
public class MyAnotherInvocationHandler implements InvocationHandler {   
      private Object target;   
 
      public void setTarget(Object target) {   
            this.target = target;   
      }   
 
      public Object invoke(Object proxy, Method method, Object[] args)   
                  throws Throwable {   
            System.out   
                        .println("AnotherConcreteDecorator: Going to execute method : doExecute");   
            if (method.getName().equals("doExecute") && args != null   
                        && args.length >= 1) {   
                  if (args[0] instanceof String) {   
                        args[0] = args[0] + " Modified by MyAnotherInterceptor";   
                  }   
            }   
            Object temp = method.invoke(target, args);   
            System.out   
                        .println("AnotherConcreteDecorator: After execute method : doExecute");   
            return temp;   
      }   
 
}  

public class MyAnotherInvocationHandler implements InvocationHandler {
      private Object target;

      public void setTarget(Object target) {
            this.target = target;
      }

      public Object invoke(Object proxy, Method method, Object[] args)
                  throws Throwable {
            System.out
                        .println("AnotherConcreteDecorator: Going to execute method : doExecute");
            if (method.getName().equals("doExecute") && args != null
                        && args.length >= 1) {
                  if (args[0] instanceof String) {
                        args[0] = args[0] + " Modified by MyAnotherInterceptor";
                  }
            }
            Object temp = method.invoke(target, args);
            System.out
                        .println("AnotherConcreteDecorator: After execute method : doExecute");
            return temp;
      }

}


客户端代码如下:

Java代码
IMyBusinessObject bo = new MyBusinessObject();  
        MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler();  
        aMyDebugInvocationHandler.setTarget(bo);  
        IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy  
                .newProxyInstance(IMyBusinessObject.class.getClassLoader(),  
                        new Class[] { IMyBusinessObject.class },  
                        aMyDebugInvocationHandler);  
 
        MyAnotherInvocationHandler aMyAnotherInvocationHandler = new MyAnotherInvocationHandler();  
        aMyAnotherInvocationHandler.setTarget(proxyObject);  
        IMyBusinessObject nextProxyObject = (IMyBusinessObject) Proxy  
                .newProxyInstance(IMyBusinessObject.class.getClassLoader(),  
                        new Class[] {IMyBusinessObject.class},  
                        aMyAnotherInvocationHandler);  
          
        System.out.println(nextProxyObject.doExecute("Hello World")); 

IMyBusinessObject bo = new MyBusinessObject();
MyDebugInvocationHandler aMyDebugInvocationHandler = new MyDebugInvocationHandler();
aMyDebugInvocationHandler.setTarget(bo);
IMyBusinessObject proxyObject = (IMyBusinessObject) Proxy
.newProxyInstance(IMyBusinessObject.class.getClassLoader(),
new Class[] { IMyBusinessObject.class },
aMyDebugInvocationHandler);

MyAnotherInvocationHandler aMyAnotherInvocationHandler = new MyAnotherInvocationHandler();
aMyAnotherInvocationHandler.setTarget(proxyObject);
IMyBusinessObject nextProxyObject = (IMyBusinessObject) Proxy
.newProxyInstance(IMyBusinessObject.class.getClassLoader(),
new Class[] {IMyBusinessObject.class},
aMyAnotherInvocationHandler);

System.out.println(nextProxyObject.doExecute("Hello World"));


输出结果:

Java代码
AnotherConcreteDecorator: Going to execute method : doExecute  
Going to execute method :doExecute  
Here in MyBusinessObject doExecute: input :Hello World Modified by MyAnotherInterceptor  
After execute method :doExecute  
AnotherConcreteDecorator: After execute method : doExecute  
Hello World Modified by MyAnotherInterceptor 

AnotherConcreteDecorator: Going to execute method : doExecute
Going to execute method :doExecute
Here in MyBusinessObject doExecute: input :Hello World Modified by MyAnotherInterceptor
After execute method :doExecute
AnotherConcreteDecorator: After execute method : doExecute
Hello World Modified by MyAnotherInterceptor
从上面的例子我们可以看出,用动态代理比静态装饰链用更少的代码为业务对象增加额外的行为。但是,如果我们像上面一样使用动态代理仍然有一些问题:当创建和链化动态代理时你仍然必须编写大量的代码,并且你还必须处理不如普通的对象创建或工厂方法的对象创建那么友善的代理接口API,还有,当我们需要代理我们的业务对象时,在多个位置重复一些代码并不是一个好主意。

下一篇博客将试图去解决这些问题。我将会编写一个暴露简单API的通用代理工厂(在其中隐藏代理对象的创建和链化),但仍可提供动态代理的扩展性。
分享到:
评论

相关推荐

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    设计模式是软件工程中的一种最佳实践,用于解决在软件开发过程中常见的问题。这些模式是由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位大师,通常被称为GoF(Gang of Four),在他们的经典著作...

    C++设计模式--基于Qt4开源跨平台开发框架

    《C++设计模式--基于Qt4开源跨平台开发框架》一书主要探讨了如何在C++编程中利用设计模式,并结合Qt4框架进行高效的跨平台应用开发。设计模式是软件工程中的重要概念,它们是经过时间和实践验证的解决特定问题的模板...

    设计模式--代理模式

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要角色,允许我们通过一个代理类来控制对原对象的访问。在《设计模式:可复用面向对象软件的基础》(通常称为GoF设计模式)中,代理模式被定义为“为其他对象...

    优秀的设计模式示例-动态代理模式

    动态代理模式是一种在运行时创建代理对象以控制或扩展原有对象行为的设计模式。它允许我们为现有的对象提供一种代理以增强其功能,而无需修改原对象的代码。动态代理模式通常用于实现对目标对象的额外操作,如日志...

    设计模式精解-GoF 23种设计模式解析附C++实现源码

    GoF(Gang of Four)所提出的23种设计模式,被认为是面向对象编程中最核心的设计原则之一。这些模式可以帮助开发者解决常见的编程问题,并提高代码的可复用性和可维护性。 #### 创建型模式 创建型模式关注的是对象...

    设计模式精解-GoF 23种设计模式解析附C++.pdf

    ### 设计模式精解——GoF 23种设计模式解析及C++实现 #### 0. 引言 设计模式作为面向对象编程的核心组成部分,是软件开发者在长期实践中总结出来的最佳实践。通过深入理解这些设计模式,我们可以更好地进行面向...

    JAVA设计模式例程-代理模式

    代理模式是一种常用的设计模式,它在软件开发中起到了桥梁的作用,允许我们为一个对象提供一个替代品或代表,以便在不改变原有对象的基础上增加额外的功能或控制访问。在这个"JAVA设计模式例程-代理模式"的压缩包中...

    java设计模式---诙谐易懂版

    根据给定文件内容,以下是关于Java设计模式的知识点说明: 1. 策略模式(Strategy Pattern)是一种行为设计模式,允许在运行时选择算法的行为。策略模式的意图是定义一系列算法,将每个算法封装起来,并使它们可以...

    java模式设计-代理模式之动态代理.ppt

    代理模式是一种设计模式,它允许我们在不修改原有对象的情况下,为现有对象添加额外的功能或控制。在Java中,动态代理是代理模式的一种实现方式,它允许我们在运行时创建代理对象,这种方式比静态代理更加灵活。动态...

    设计模式精解-GoF 23种设计模式解析附C++实现源码.pdf

    GoF(Gang of Four)所提出的23种设计模式被视为面向对象设计的核心内容之一。本文旨在深入解析这些设计模式,并通过C++实现来帮助读者更好地理解和应用这些模式。 #### 1. 创建型模式 创建型模式关注的是对象的...

    设计模式精解-GoF23种设计模式解析附C++实现源码

    设计模式是软件工程中的一种重要思想,它是在特定情境下,为解决常见问题而形成的一套最佳实践。GoF(Gang of Four)23种设计模式是软件开发中的经典,由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides...

    Java设计模式----通俗易懂版

    Java设计模式是软件工程中的一种重要思想,它总结了在解决特定问题时,程序员们反复使用的一些最佳实践和解决方案。这个资源"Java设计模式----通俗易懂版"显然是一个专门针对初学者或需要深入理解设计模式的开发者...

    设计模式课件大全

    设计模式10-代理模式、结构型模式大复习 设计模式11-行为模式-责任链、命令模式 设计模式12-解释器模式 设计模式13-迭代器模式 设计模式14-中介者模式、备忘录模式 设计模式15-观察者模式、状态模式 设计模式16-策略...

    设计模式精解-GoF 23种设计模式解析附C++实现源码 完整版

    《设计模式精解-GoF 23种设计模式解析附C++实现源码 完整版》是一份深入探讨软件工程中经典设计模式的重要资料,涵盖了面向对象编程中的核心设计原则和实践。这份资源主要关注GoF(Gang of Four,即《设计模式:可...

    优秀的设计模式示例-静态代理模式

    静态代理模式是设计模式中的一种,属于结构型模式,主要用在我们想要在不修改原有对象的基础上,为对象添加额外功能或者控制对象的行为时。在这个例子中,"优秀的设计模式示例-静态代理模式"提供了实际项目中的代码...

    Java设计模式-代理模式例子

    在这个“Java设计模式-代理模式例子”中,我们可能能看到如何创建静态代理类,以及如何利用`Proxy`和`InvocationHandler`创建动态代理。源码分析可以帮助我们更好地理解代理模式的实现细节,并能将其运用到自己的...

    代理模式-静态动态代理-jdk动态代理-cglib动态代理

    代理模式是一种设计模式,它允许我们在不修改原有对象的情况下,为对象添加新的功能或行为。在Java中,代理模式有多种实现方式,包括静态代理、JDK动态代理和CGLIB动态代理。 **静态代理** 静态代理是最早也是最...

    Java设计模式-代理模式

    代理模式是这些设计模式中的一种,它为其他对象提供一种代理以控制对这个对象的访问。代理模式的核心思想是在目标对象和客户端之间插入一个代理对象,代理对象可以扩展目标对象的功能,同时也能控制对目标对象的访问...

Global site tag (gtag.js) - Google Analytics