`

代理模式,静态代理与动态代理

    博客分类:
  • java
阅读更多

代理模式

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式一般涉及到的角色有:

抽象角色:声明真实对象和代理对象的共同接口;

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献1)

以下以《Java与模式》中的示例为例:

抽象角色:

abstract public class Subject

{

    abstract public void request();

}

真实角色:实现了Subject的request()方法。

public class RealSubject extends Subject

{

       public RealSubject()

       {

       }

      

       public void request()

       {

              System.out.println("From real subject.");

       }

}

代理角色:

public class ProxySubject extends Subject

{

    private RealSubject realSubject;  //以真实角色作为代理角色的属性

      

       public ProxySubject()

       {

       }

 

       public void request()  //该方法封装了真实对象的request方法

       {

        preRequest(); 

              if( realSubject == null )

        {

                     realSubject = new RealSubject();

              }

        realSubject.request();  //此处执行真实对象的request方法

        postRequest();

       }

 

    private void preRequest()

    {

        //something you want to do before requesting

    }

 

    private void postRequest()

    {

        //something you want to do after requesting

    }

}

客户端调用:

Subject sub=new ProxySubject();

Sub.request();

       由以上代码可以看出,客户实际需要调用的是RealSubject类的request()方法,现在用ProxySubject来代理RealSubject类,同样达到目的,同时还封装了其他方法(preRequest(),postRequest()),可以处理一些其他问题。

       另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。

 

2.动态代理类

       Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:

(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, J2EEjava语言JDK1.4APIjavalangObject.html">Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。


(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:

Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。

Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

 

       所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。(参见文献3)

    在使用动态代理类时,我们必须实现InvocationHandler接口,以第一节中的示例为例:

抽象角色(之前是抽象类,此处应改为接口):

public interface Subject

{

    abstract public void request();

}

具体角色RealSubject:同上;

 

代理角色:

import java.lang.reflect.Method;

import java.lang.reflect.InvocationHandler;

 

public class DynamicSubject implements InvocationHandler {

  private Object sub;

 

  public DynamicSubject() {

  }

 

  public DynamicSubject(Object obj) {

    sub = obj;

  }

 

 

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    System.out.println("before calling " + method);

 

    method.invoke(sub,args);

 

    System.out.println("after calling " + method);

    return null;

  }

 

}

 

       该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;此外,在该类还实现了invoke方法,该方法中的

method.invoke(sub,args);

其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,args为执行被代理对象相应操作所需的参数。通过动态代理类,我们可以在调用之前或之后执行一些相关操作。

客户端:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Proxy;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

 

public class Client

{

 

    static public void main(String[] args) throws Throwable

       {

      RealSubject rs = new RealSubject();  //在这里指定被代理类

      InvocationHandler ds = new DynamicSubject(rs);  //初始化代理类

         Class cls = rs.getClass();

      //以下是分解步骤

      /*

      Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ;

      Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class});

      Subject subject =(Subject) ct.newInstance(new Object[]{ds});

     */

     //以下是一次性生成

      Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(),

                                 cls.getInterfaces(),ds );

 

      subject.request();

}

       通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系(参见文献2)。

分享到:
评论
2 楼 kjmmlzq19851226 2013-06-19  
private RealSubject realSubject;  //以真实角色作为代理角色的属
yangxinxyx 写道
public class ProxySubject extends Subject

{

    private RealSubject realSubject;  //以真实角色作为代理角色的属性

      

在代理模式的时候,此处应该是一个接口声明,而不是直接的真实BEAN。 楼主这样的代码并没有真正体现出代理的优势.

个人觉得这里应该是Object,如果是jdk动态代理应该注入一个接口实现,如果是委托代理,这里应该是被代理对象的子类
1 楼 yangxinxyx 2012-01-18  
public class ProxySubject extends Subject

{

    private RealSubject realSubject;  //以真实角色作为代理角色的属性

      

在代理模式的时候,此处应该是一个接口声明,而不是直接的真实BEAN。 楼主这样的代码并没有真正体现出代理的优势.

相关推荐

    Java 代理 代理模式 静态代理与动态代理 常见的动态代理实现 .md

    静态代理与动态代理的区别 代理模式可以进一步细分为静态代理和动态代理。 - **静态代理**:在程序编译时就已经确定代理类的具体实现方式。这意味着每次需要代理不同的操作时,都需要修改代理类的代码,这违反了...

    Java设计模式——代理设计模式(静态代理和动态代理)

    代理设计模式分为静态代理和动态代理两种类型。 ### 静态代理 静态代理是在编译时就已经确定了代理关系,代理类和真实类的关系是硬编码在代理类中的。下面我们将详细介绍静态代理的实现方式: 1. **定义接口**:...

    java静态代理、动态代理、装饰设计模式

    Java提供了两种实现代理的主要方式:静态代理和动态代理。 **静态代理** 静态代理是最基础的形式,它需要程序员手动创建一个代理类,该类实现了与目标类相同的接口。代理类持有目标类的引用,并在调用目标类方法...

    Java静态代理和动态代理

    四、静态代理与动态代理的比较 1. **灵活性**:动态代理比静态代理更灵活,因为不需要预先编写代理类的源代码,可以适应接口的变化。 2. **代码量**:静态代理需要为每个委托类编写单独的代理类,如果委托类很多,会...

    代理模式的各种实现 (动态代理、静态代理)

    代理模式在Java中主要有两种实现方式:静态代理和动态代理,其中动态代理又分为JDK动态代理和CGlib代理。 1. 静态代理 静态代理是程序员手动创建代理类并实现与目标类相同接口的方式。在静态代理中,代理类和目标类...

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理) Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解...

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

    静态代理模式的核心思想是通过代理类来代理原始对象(也称为真实对象或服务对象),代理类通常与原始对象实现相同的接口,以便在客户端代码中可以透明地调用。代理类可以在调用真实对象的方法前后添加额外的操作,...

    Java 静态代理模式

    静态代理模式是一种结构型设计模式,其核心思想是通过创建一个代理类,这个代理类作为原对象的替代,提供与原对象相同的方法调用,但可以在调用前后添加额外的操作。这种模式在不修改原始对象代码的情况下,可以用于...

    代理模式(Proxy Pattern) 1. 概述 1.1 基本概念 1.2 为什么需要代理模式 1.3 代理模式的四个角色 2. 代理模式的类型 2.1 静态代理 2.2 JDK动态代理

    代理模式(Proxy Pattern) 1. 概述 1.1 基本概念 1.2 为什么需要代理模式 ...9.2 静态代理与动态代理应该如何选择? 9.3 Spring AOP使用的是什么代理模式? 9.4 CGLIB代理和JDK动态代理有什么区别? 10. 总结

    静态代理与动态代理Demo

    代理模式分为静态代理和动态代理两种主要形式,每种都有其特定的应用场景和优势。下面我们将深入探讨这两种代理模式,并通过一个“黄牛买票”的例子来具体说明。 首先,我们来看静态代理。静态代理是程序员在编译时...

    静态代理和动态代理

    根据实现方式的不同,代理模式可以分为静态代理和动态代理两种。 ### 静态代理 静态代理是在编译时就已经确定了代理关系。我们需要创建一个代理类,该类实现与目标对象相同的接口,并在代理类的方法中调用目标对象...

    JAVA静态代理和动态代理

    静态代理是程序员手动创建代理类并实现与目标对象相同的接口。代理类和目标类都必须实现相同的接口,这样代理类就可以在调用目标对象方法的同时添加额外的功能。以下是一个简单的静态代理模式示例: 1. 定义接口: ...

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

    在Java中,代理模式有多种实现方式,包括静态代理、JDK动态代理和CGLIB动态代理。 **静态代理** 静态代理是最早也是最基础的代理实现方式。在静态代理中,我们需要创建一个代理类,这个代理类与原始类(被代理类)...

    Java静态代理与动态代理demo

    Java提供了两种实现代理模式的方式:静态代理和动态代理。 **静态代理** 静态代理是在编译时就已经确定了代理类,通过继承或实现目标接口来创建代理类。以下是一个简单的静态代理实现示例: ```java // 目标接口 ...

    包含静态代理和动态代理demo代码

    与静态代理相比,动态代理更灵活,它在运行时动态地创建代理类。Java中的动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。动态代理的步骤如下: 1. 定义一个接口...

    Java代理模式模板代码,包含动态代理与静态代理

    总结,Java代理模式提供了两种实现方式,静态代理适用于代理类数量较少且不需要频繁改动的情况,而动态代理则更加灵活,适用于代理类数量多或者需要动态改变代理行为的场景。了解并熟练运用这两种代理模式,可以极大...

    代理设计模式:静态代理和动态代理的理解、实现与区别(优缺点)与SpringAOP的3种配置方式案例工程代码

    本资源主要涵盖了静态代理和动态代理两种常见类型的代理模式,以及Spring AOP中动态代理的三种配置方式。以下是详细的知识点解析: ### 静态代理 静态代理是程序员手动创建代理类并实现相同接口的方式。代理类和...

    java 设计模式之代理模式(Proxy Pattern)实现代码及设计详解:动态代理模式、静态代理模式

    代理模式分为两种主要类型:静态代理和动态代理。 **静态代理** 在静态代理中,代理类和目标类都是在编译时就已经确定的。我们首先创建一个目标类接口,然后创建一个实现这个接口的代理类,同时代理类还持有目标类...

    设计模式(八)之静态代理模式.zip

    在软件设计领域,设计模式是一种经过验证的、通用的解决方案,用于解决常见...在实际开发中,根据项目需求和场景,可以考虑使用动态代理模式(如Java的`java.lang.reflect.Proxy`)来克服这些缺点,实现更灵活的代理。

    动态代理和静态代理demo

    代理模式通常分为静态代理和动态代理两种实现方式,这里我们将详细探讨这两种代理模式,并通过一个简单的Java示例进行演示。 ### 静态代理 静态代理是最基础的代理形式,它的实现主要依靠继承或接口实现。在静态...

Global site tag (gtag.js) - Google Analytics