5个答案 按时间排序 按投票排序
-
采纳的答案
代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献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类)也可以动态改变,从而实现了非常灵活的动态代理关系
2009年4月21日 03:48
-
Spring 中常常使用Proxy,是为了在真实目标类上,加入一些其它操作,而这些操作的细节都交给代理处理,你只需要集中目标类功能的实现。
2009年4月21日 00:26
-
代理的作用太广了。。。
日常的,如使用代理上网。
在jive 论坛程序大量使用Proxy,它封装了权限,缓存等,当使用某个类,都是返回它的Proxy类,如使用ForumManager,它会返回一个ForumManager的Proxy,加入了一些其它控制因素。
在Jmock中同样是创建一个Proxy,模拟真实对象。
在Spring中,提供了多种代理,利用jdk中api,需要提供接口。而cglib是不需要的,可以直接创建类的Proxy。2009年4月21日 00:22
相关推荐
2. **为什么使用动态代理?** 使用动态代理的原因主要有以下几点: - **增强功能**:可以在不修改原始业务代码的情况下,为已有接口或类添加新的功能,如日志记录、事务控制、权限验证等。 - **解耦合**:动态...
#### 二、为什么要使用动态代理? 传统的数据库连接管理方式通常涉及到显式地创建和关闭连接,这种方式存在以下问题: 1. **资源浪费**:每次建立连接都需要消耗系统资源,频繁地创建和销毁连接会导致资源浪费。 2...
对代理模式与Java动态代理类的理解说明
为什么要有 hashCode hashCode 是 Java 中一个非常重要的概念。它用于判断两个对象是否相等。在 HashSet 中,hashCode 是用来判断对象是否重复出现的。它可以快速地判断对象是否相等,以便快速地存储和检索对象。 ...
代理模式在Java中有两种常见的实现方式:静态代理和动态代理。静态代理是通过程序员显式创建代理类来实现的,而动态代理则利用Java的反射API在运行时动态创建代理对象。 1. **静态代理**:在静态代理中,我们需要为...
原理是,利用反射机制,动态生成匿名类继承 `Proxy` 类并且实现了要代理的接口,由于 Java 不支持多继承,所以 JDK 动态代理不能代理类。例如,在上面的例子中,我们定义了一个接口 `IHello`,然后创建了一个实现类 ...
### 深入研究Java类加载机制 #### 一、Java类加载机制概述 Java类加载机制是Java程序运行的第一步,它对于理解Java虚拟机(JVM)的行为至关重要。类加载过程涉及到类的加载、链接(验证、准备、解析)、初始化等...
在Java中,代理模式有静态代理和动态代理两种实现方式。 ### 静态代理 静态代理是最基础的形式,它需要我们为每一个被代理的对象创建一个对应的代理类。在静态代理中,代理类通常会实现与被代理类相同的接口,以...
在Java中,有两种方式实现动态代理:一是使用`java.lang.reflect.Proxy`类,二是使用CGLIB库。Proxy类提供了创建动态代理对象的机制,它需要一个实现了`java.lang.reflect.InvocationHandler`接口的类来处理方法调用...
`PDU`(协议数据单元)是SNMP通信中的一个核心概念,它定义了SNMP操作的具体内容,例如:要获取哪个对象的值,要设置哪个对象的值等。`VariableBinding`类用于定义一个或多个对象的标识符(OID)与它们的值之间的...
动态代理的好处在于不需要为每个目标类创建一个单独的代理类。以下是一个动态代理的例子: ```java // 接口 interface Service { void doSomething(); } // 代理的实现 class DynamicProxy implements ...
2. **代理模式**:代理模式也属于创建型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。在代理模式中,代理类作为真实对象的代表,可以在客户端和目标对象之间起到中介作用,例如,可以添加额外的功能...
设计模式是软件工程中的一种最佳实践,它是在特定情境下为解决常见问题而形成的一套可复用的解决方案模板。在Java语言中,设计模式的应用广泛且深入,可以帮助开发者写出更加灵活、可维护和可扩展的代码。《设计模式...
对比之下forward更加高效,并且它有助于隐藏实际地址,但是有些情况则必须使用redirect,否则会报异常。 jsp中动态include和静态include的区别? 答:动态include用jsp:include实现,适用于动态页面,可以携带参数 ...
在Java编程中,代理模式是一种常见的设计模式,它允许我们为一个对象提供一个代理以控制对这个对象的访问。代理模式通常用于增加额外的功能,如日志、事务管理或者权限控制,而不会改变原始对象的接口。根据实现方式...
Java中常见的工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式。 除了这两种模式,设计模式还有许多其他种类,如"建造者模式"用于复杂对象的构建;"观察者模式"用于实现对象之间的发布/订阅机制;"装饰器模式...
在Java中,适配器模式可以通过类适配器或对象适配器来实现,它可以帮助我们复用现有的类,即使其接口与我们的需求不匹配。 此外,还有许多其他的设计模式,如单例模式、建造者模式、观察者模式、装饰器模式、代理...
Q0058 一个Java抽象类声明了一个方法并会抛出一个异常,问继承这个抽象类的子类,实现了这个方法,这个方法声明是不是一定要抛出一模一样的异常,可不可以不抛,或者抛出的异常比抽象类的异常范围大,或者小?...
在Java中,有两种常见的动态代理方式:Java内置的Java.lang.reflect.Proxy类和第三方库如CGlib。Java内置的Proxy类需要目标类实现至少一个接口,然后才能创建代理对象。然而,如果目标类没有实现任何接口,我们就不...