这几天在学习java的设计模式,发现有很多的思想是值的学习的。模式应该说是任何编程语言都有,只是编码风格不同吧。我是初学者,以下是我做的一个关于动态代理的例子。如有不正确的地方希望大家指正。
如果使用静态的代理模式,那么真实的角色必须是事先已经存在的,并将其作为代理对象的内部属性.但是在实际使用时,一个真实角色必须对应一个代理角色、如果大量使用会导致类的急剧膨胀;此外,如果事先不知道真实角色,该如何使用代理呢?这个问题可以使用java的动态代理来解决。
Java的动态代理类位于java.lang.reflect包下,一般使用到两个部分:
(1)、interface InvocationHandler;
该接口仅仅定义了一个方法: public Object invoke(Object proxy,Method method,Object[] args)
throws Throwable
在实际使用时第一个参数proxy一般是一个代理类,method是代理的方法如上例中的request,args为该方法(request)的参数数组。这个抽象方法在代理类中动态的实现。
参数?对象
(2)、Proxy:该类即为动态的代理类,作用类似于上例中的ProxySubject,主要包含以下内容:
protected Proxy(InvocationHandler h)
----- 使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例。在开发中h一般是实现了InvocationHandler接口的类。且这个方法无法在外部直接使用。
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException
------ 获得一个代理类,其中loader是类加载器,interfaces是真实类所拥有的全部接口(数组);
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
----- 返回代理类的一个实例(秘书),返回后的代理类可以被当作被代理类使用(可使用被代理类的在subject接口中声明的方法)(秘书代替局长)
所谓的动态代理(dynamic proxy)是这样的一中Class:他是在运行时生成的类class,在生成他(指这个class)时你必须提供给他一组interface,然后该class就宣称他实现了这些interface。由于使用的是在运行时生成的类,不能明确的让他继承和实现某一个类或者接口,所以必须在方法中提供给他相应的已经定义的接口。
你当然可以把该class的实例当作这些interface中的任何一个来用(这个类已经实现了多个接口)。当然这个动态的代理类就是一个代理类(Proxy),他不会替你做实质性的工作(秘书不会代替局长做实质性的工作),在生成他的一个实例时你必须提供一个Handler(InvocationHandler),由他(调用invoke方法执行)接管实例的工作。
在使用动态代理类时,我们必须实现InvocationHandler接口。
在动态代理中代理必须是一个接口
一个接口:
package com.hhl.testForDynamicProxy;
public interface Subject {
/* 在动态代理中一般是接口 而不是抽象类,虽然是抽象类的变体*/
public void request(int i);
public void showAuthorName(String str);
}
要被代理的两个类:
package com.hhl.testForDynamicProxy;
public class RealSubject implements Subject {
/*
* 真正的业务类 在代理中是被代理类
* */
public void request(int i) {
System.out.println("==RealSubject request invoke " + i);
}
public void showAuthorName(String str) {
System.out.println("==RealSubject showAuthorName " + str);
}
}
package com.hhl.testForDynamicProxy;
public class AnotherRealSubject implements Subject {
public void request(int i) {
System.out.println(" AnotherSubject request " + i );
}
public void showAuthorName(String str) {
System.out.println(" AnotherSubject showAuthorName " + str );
}
}
一个Invocakation类:
package com.hhl.testForDynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicSubjectHandler implements InvocationHandler {
/* 注入被代理类 并将其作为属性 操作是直接执行这个被代理类的方法 */
private Object obj;
public DynamicSubjectHandler(Object obj){
this.obj = obj;
}
public Object invoke(Object object, Method method, Object[] arg2)
throws Throwable {
System.out.println(" before " + method);
method.invoke(this.obj, arg2);
System.out.println(" after " + method);
return null;
}
}
客户端调用:
package com.hhl.testForDynamicProxy;
import java.lang.reflect.Proxy;
public class Test {
/**
* @param args
* @author hehailin 2008-12-11
*/
public static void main(String[] args) {
RealSubject rsj = new RealSubject();
AnotherRealSubject arsj = new AnotherRealSubject();
DynamicSubjectHandler dsHandler1 = new DynamicSubjectHandler(rsj);
DynamicSubjectHandler dsHandler2 = new DynamicSubjectHandler(arsj);
Class<?> c1 = rsj.getClass();
Class<?> c2 = arsj.getClass();
Subject s1 = (Subject)Proxy.newProxyInstance(c1.getClassLoader(), c1.getInterfaces(), dsHandler1);
Subject s2 = (Subject)Proxy.newProxyInstance(c1.getClassLoader(), c2.getInterfaces(), dsHandler2);
/*
* 获取一个RealSubject AnotherRealSubject的代理类,可以将dsHandler2也换成dsHandler1看看...
* 这里RealSubject和AnotherRealSubject都实现了一个接口,所以在getInterfaces()时都返回一样的结果Subject
* 使用一个ClassLoader当然也是可以的
*
* 每个代码实例都具有一个关联的调用处理程序dsHandler。对代理实例调用方法时,
* 将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
*
* Proxy.newProxyInstance() 获得的代理必须转换后接口才能使用
* 使用RealSubject 就不行 转型失败,这个可能是不能实现向下转型
*
*
* c.getClassLoader() 获取一个用于加载一个RealSubject/AnotherRealSubject对象的加载类
* c.getInterfaces() 获取一个RealSubject/AnotherRealSubject对象的所有接口的class
* dsHandler 实际调用RealSubject中的方法的处理程序,接管服务
* */
s1.request(3);
s2.showAuthorName(" hehailin ");
s2.request(10);
s2.showAuthorName(" |--hehailin ");
}
}
输出结果:
before public abstract void com.hhl.testForDynamicProxy.Subject.request(int)
==RealSubject request invoke 3
after public abstract void com.hhl.testForDynamicProxy.Subject.request(int)
before public abstract void com.hhl.testForDynamicProxy.Subject.showAuthorName(java.lang.String)
AnotherSubject showAuthorName hehailin
after public abstract void com.hhl.testForDynamicProxy.Subject.showAuthorName(java.lang.String)
before public abstract void com.hhl.testForDynamicProxy.Subject.request(int)
AnotherSubject request 10
after public abstract void com.hhl.testForDynamicProxy.Subject.request(int)
before public abstract void com.hhl.testForDynamicProxy.Subject.showAuthorName(java.lang.String)
AnotherSubject showAuthorName |--hehailin
after public abstract void com.hhl.testForDynamicProxy.Subject.showAuthorName(java.lang.String)
分享到:
相关推荐
代理模式的核心思想是通过代理类来代替实际的对象,使得客户端可以通过代理类与真实对象进行交互,而无需直接操作真实对象,这样可以增加程序的灵活性,同时也便于管理或扩展系统。 代理模式主要分为以下几种类型:...
Proxy模式是一种设计模式,它允许我们为一个对象创建一个代理对象,这个代理对象在客户端和目标对象之间起到中介的作用。这种模式在软件工程中广泛应用,主要用于控制对真实对象的访问,提供额外的功能,如日志、...
全部高质量代理模式proxy的java源程序 java.proxy,代理模式源码,设计模式,apache开源项目源码commons-proxy-1.0-src 各种代理模式操作的工具类源码以及代理模式案例源码,你会从中得到意想不到的效果! apache...
在`proxy-learn`这个压缩包中,应该包含了这两种代理模式的详细示例代码,供初学者参考学习。对于初学者来说,理解并掌握代理模式是提升编程能力的重要步骤,它能帮助我们更好地理解和应用面向对象设计原则。
总结来说,"proxy.rar"压缩包提供了Java编程中三种代理模式的源代码实例,通过学习这些代码,开发者可以深入理解代理模式的原理和实现,同时掌握泛型在实际项目中的应用。对于提高代码的可扩展性和可维护性,这些都...
至于`中国java下载站.url`,这可能是一个链接到Java学习资源的网址,它并非代理模式的一部分,但强调了学习Java的重要性,尤其是对于理解和实践设计模式,如代理模式,这些资源可以帮助开发者扩展知识面,提升技能。...
### C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) #### 重要概念:代理模式 代理模式是一种常用的结构型设计模式,它通过为另一个对象提供一个代理,来控制对该对象的访问。这种模式在软件工程中...
**代理模式(Proxy Pattern)**是软件设计模式中的结构型模式之一,它在对象访问控制、增加额外功能或在客户端与目标对象之间提供一个中介等方面有广泛的应用。在代理模式中,代理类作为真实对象的代表,它持有真实...
总结来说,“spring proxy代理模仿”项目是对Spring AOP代理机制的实践与理解,通过此项目,你可以深入学习到如何在不修改原有业务代码的基础上,利用Spring的动态代理能力添加额外的功能,提升代码的可维护性和复用...
在这个"代理模式的使用示例程序"中,我们可以通过分析"interceptor"类,学习如何实现和应用代理模式,包括如何设置拦截逻辑,以及如何通过代理对象透明地控制和增强原始对象的行为。这对于我们理解和提升面向对象...
### C++设计模式之代理模式详解 #### 一、引言 ...通过本文的学习,相信读者已经对代理模式有了较为全面的理解。在未来的设计与开发过程中,合理地运用代理模式,可以有效提升软件架构的灵活性和扩展性。
* Protection Proxy:可以使用代理模式来保护目标对象的访问。 * Cache Proxy:可以使用代理模式来缓存对象的访问结果。 知识点5:代理模式的优点和缺点 代理模式的优点包括: * 可以帮助客户端访问目标对象,而...
对于学习和应用 Java 代理模式来说,熟悉这些源码是非常有益的。 至于压缩包中的 `sample3` 文件,由于没有提供具体内容,我们无法进一步分析。但根据上下文,它可能是包含示例代码或数据的文件,可能与上述代理...
总的来说,通过这个proxy代理程序实例,我们可以学习到如何在Linux环境下实现一个基础的网络代理服务,包括创建和管理套接字、处理网络连接、进行数据传输等核心概念。同时,这也是一次实践网络编程基础知识的机会,...
6. **中国java下载站.url**:这可能是一个链接,指向一个Java资源下载网站,可能与学习代理模式或获取相关库有关,但具体用途需查看链接内容。 7. **开发实践**:在实际开发中,代理模式广泛应用于远程代理(如RPC...
通过查看代码,我们可以更深入地学习如何在实际项目中运用代理模式。然而,由于没有具体的代码内容,这里无法提供详细的代码解析。如果你能提供代码示例,我可以帮助你深入解析其工作原理和实现细节。
代理模式是一种常用的设计模式,它在软件开发中起到了中介或者代表的作用。代理模式的主要目的是为其他对象提供一种代理以...在学习代理模式时,可以尝试编写不同类型的代理,并在实际项目中寻找应用实例,以加深理解。
通过学习和实践代理模式,开发者可以更好地理解和掌握面向对象设计原则,如单一职责原则和开闭原则,同时也能提高代码的复用性和可测试性。在Java世界里,设计模式是连接理论和实践的重要桥梁,是每个专业开发者必备...