这篇文章忘记从哪里转的,对作者表示感谢吧。
1. 代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或不能直接引用另一个对象,而代理对象能在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的一起接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而能操作真实对象,同时代理对象提供和真实对象相同的接口以便在所有时刻都能代替真实对象。同时,代理对象能在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献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, 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)。
参考文献:
1. 阎宏,《Java 与模式》
2. 透明,《动态代理的前世今生》
3.Forest Hou,《Dynamic Proxy 在 Java RMI 中的应用》
分享到:
相关推荐
与静态代理不同,动态代理在程序运行时生成,利用Java的反射API动态创建代理类。动态代理适用于那些在运行时才知道需要代理的对象或者代理行为的情况。Java提供了`java.lang.reflect.Proxy`类和`java.lang.reflect....
代理模式分为静态代理和动态代理两种主要形式,每种都有其特定的应用场景和优势。下面我们将深入探讨这两种代理模式,并通过一个“黄牛买票”的例子来具体说明。 首先,我们来看静态代理。静态代理是程序员在编译时...
本主题将深入探讨JVM技术,特别是反射与动态代理这两个关键特性。 一、JVM技术 1. 类加载机制:JVM通过类加载器(ClassLoader)来加载.class文件,分为启动类加载器、扩展类加载器和应用程序类加载器。类的加载...
在提供的`动态代理与RMI远程调用.ppt`中,可能会详细解释这两个概念,通过PPT的讲解和实例,可以更直观地理解动态代理和RMI的工作原理。同时,`src`目录下的源码文件则提供了具体的实现示例,读者可以通过阅读代码,...
与JDK动态代理不同,CGLIB并不依赖接口,而是通过字节码技术生成一个被代理类的子类来实现。这使得CGLIB能够代理没有实现接口的类。CGLIB的核心是ASM库,它能直接操作字节码生成新的类。在Spring中,如果目标类没有...
动态代理和AOP是Java和Spring框架中的重要概念,它们为开发者提供了强大的代码复用和模块化设计的能力。本文将深入解析这两个主题,并结合提供的源码进行详细讲解。 首先,让我们了解一下动态代理。在Java中,动态...
Java动态代理是面向切面编程(AOP)的一种实现方式,它允许我们在不修改原有代码的情况下,为已有的对象添加额外的功能。在Web开发中,动态代理常常用于增强业务逻辑,比如日志记录、权限检查等,使得代码更加模块化...
### JAVA类加载机制与动态代理 #### 一、类加载机制 ##### 1.1 类加载的时机 类加载机制负责将描述类的数据从`.class`文件加载到内存,并进行必要的校验、转换解析和初始化,使之成为可以被Java虚拟机直接使用的...
Java中的动态代理、反射和拦截器是面向对象编程中非常重要的技术,它们在实现灵活性、扩展性和代码解耦方面发挥着关键作用。本资源提供的示例涵盖了这些核心概念,通过JDK动态代理、CGLIB动态代理以及拦截器链的实践...
Java JDK 动态代理是一种强大的特性,它允许我们在运行时创建代理对象,这些代理对象可以扩展或增强已存在的接口实现。动态代理在处理AOP(面向切面编程)场景、事件监听、性能监控等方面有着广泛的应用。下面我们将...
在编程领域,动态代理和工厂方法是两种非常重要的设计模式,它们在软件开发中起着至关重要的作用。这里我们将深入探讨这两种模式,并结合提供的文件名,即“005_Factory_Series_DesignPattern”和“006_Dynamic_...
动态代理和静态代理是代理模式的两种主要实现方式,它们在Java编程中尤为常见。 首先,让我们从静态代理开始。静态代理是手动创建的代理类,它通常与被代理类位于同一个包下,并且实现相同的接口。在这个过程中,...
在Java中,基于动态代理和反射机制实现ORM可以提高代码的可维护性和灵活性。本篇文章将深入探讨如何在Java环境下,结合MySQL数据库,利用动态代理和反射技术来实现简单的ORM框架。 首先,我们需要了解动态代理和...
动态代理是指在程序运行时,根据指定的接口动态创建一个代理类,并且这个代理类可以实现与被代理对象相同的行为。在Java中,动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler...
动态代理在Java编程中是一种非常重要的技术,它允许我们在运行时创建对象的代理,从而可以在不修改原有代码的情况下,为对象添加额外的功能。本压缩包包含关于三种主要的动态代理实现方式:JDK动态代理、CGLIB以及...
动态代理和Spring AOP(面向切面编程)是两个关键的设计概念,它们在实现高效、模块化的系统中起着至关重要的作用。本文将深入探讨这两个概念,并结合实际应用进行解析。 首先,让我们理解什么是动态代理。动态代理...
它在许多场景下被广泛使用,特别是在实现Java的动态代理机制时。动态代理是一种技术,允许我们在运行时创建一个对象的代理,这个代理对象能够拦截并处理对原对象的调用。CGlib就是为这种需求提供支持的一个库。 ...
动态代理是实现AOP的一种常见技术,它允许我们在运行时创建对象的代理,从而在不修改原有代码的情况下添加额外的功能。本篇文章将深入探讨如何使用动态代理实现AOP。 1. **AOP概念** - AOP(Aspect Oriented ...