代理模式代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献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 [url=file:///D:技术文档J2EEjava语言JDK1.4APIjavalangreflectProxy.html#newProxyInstance(java.lang.ClassLoader, java.lang.Class[], java.lang.reflect.InvocationHandler)]newProxyInstance[/url](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)。
更多请进入
code110技术导航网
分享到:
相关推荐
8. **反射**:探讨如何在运行时动态获取类的信息并操作类的对象,以及其在插件化、序列化和动态代理中的应用。 9. **泛型**:讲解泛型的引入、使用规则,以及泛型通配符和边界。 10. **网络编程**:涉及Socket编程,...
虽然不常用,但在某些场合(如插件系统、序列化、动态代理)是必不可少的。 9. **泛型**:泛型是Java 5引入的新特性,用于增强类型安全,减少类型转换,并允许编译器进行更严格的检查。理解和运用泛型,可以编写出...
这份“Java基础知识复习资料”涵盖了学习Java编程所必需的关键概念和技术,旨在帮助初学者巩固基础,同时也适合有经验的开发者进行回顾。 1. **Java语法基础** - **变量与数据类型**:Java提供了基本数据类型(如...
- 动态代理的理解和使用。 10. **设计模式** - 常见的设计模式如单例模式、工厂模式、装饰者模式、观察者模式等的应用场景和实现。 11. **JVM** - 理解JVM的内存模型,包括堆、栈、方法区、本地方法栈等。 - ...
在本教程中,我们将深入探讨Java编程语言中的两个核心概念:动态代理和Java 8的新特性,特别是关于ClassLoader的部分。动态代理是Java中一个强大的工具,它允许在运行时创建对象,这些对象可以作为其他对象的代理,...
文档可能会涉及JAVA高级特性,比如反射、动态代理、注解、Lambda表达式、Stream API等。这些都是JAVA 8及以后版本新增的重要功能,对于提升代码质量和效率至关重要。 在设计模式方面,"面试之葵花宝典"可能包含了...
- **动态代理**:在运行时创建接口的代理实现。 10. **JVM内存模型** - **堆内存**:对象的存储区域。 - **栈内存**:方法调用时的局部变量。 - **方法区**:存储类信息、常量、静态变量等。 通过深入学习这些...
- **反射**:学习通过反射动态访问类、接口、方法和字段,以及动态代理。 - **注解(Annotation)**:了解注解的定义、使用和自定义注解,以及元注解的应用。 - **集合框架高级特性和并发工具类**:如...
- 动态代理:了解Proxy和InvocationHandler,实现动态绑定。 11. **Java模块化(Java 9+)** - 模块系统:模块的概念,模块描述符(module-info.java)的编写。 12. **JDBC(Java Database Connectivity)** - ...
7. **反射机制**:Java反射机制允许在运行时动态获取类的信息并操作类的对象,是Java的高级特性之一,常用于插件开发、动态代理等场景。 8. **JVM内存模型**:理解Java虚拟机的工作原理,特别是内存区域(如堆、栈...
它在插件系统、序列化、动态代理等领域有广泛应用。 十、Java虚拟机(JVM) JVM是Java程序的运行环境,负责加载类、执行字节码、垃圾回收等。了解JVM的工作原理和调优技巧,对于提升程序性能至关重要。 这份"java...
这些知识点是Java程序员必备的基础技能,通过复习试题集,可以有效地检验和巩固学习成果,提高问题解决能力,为面试和实际项目开发做好准备。对于每个知识点,不仅需要理解概念,还需要通过编写代码来加深理解和应用...
这是许多高级功能,如动态代理、元编程的基础。 9. **泛型**:泛型引入于Java 5,提高了代码的类型安全性和重用性。理解如何声明和使用泛型类、接口和方法是现代Java编程的必备技能。 10. **JVM与内存管理**:理解...
本学习笔记主要涵盖了Java的基础知识,包括面向对象、集合、IO流、多线程、反射与动态代理以及Java 8的新特性等方面,旨在帮助初学者或有经验的开发者巩固和提升Java编程技能。 1. 面向对象(OOP):Java的核心是...
11. **反射与动态代理**:反射机制允许在运行时检查类的信息并操作对象,动态代理则允许在运行时创建代理对象,实现对原对象的增强功能。 通过解读书中提供的练习题解答,学习者可以更深入地理解和应用这些知识点,...
9. **反射**:Java反射机制允许在运行时动态地获取类的信息并操作类的对象,是Java强大的功能之一,常用于插件开发、序列化、动态代理等场景。 10. **Java API**:熟悉Java标准库中的各种类和接口,如Collections、...
7. **反射机制**:反射允许程序在运行时动态地获取类的信息并操作类的对象,是Java灵活性的重要体现,广泛应用于插件系统、动态代理等领域。 8. **泛型**:泛型引入了类型参数,提高了代码的类型安全性和重用性,...
Java CORBA(Common Object Request Broker Architecture,公共对象请求代理架构)是Java平台中用于实现分布式计算的技术。它允许不同计算机上的对象互相通信,仿佛它们在同一个应用程序中一样。本复习及开发文档...