`

【解惑】 Java代理机制

阅读更多

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

 

 

代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

 

 

//抽象角色: 
public interface Subject{ 
    void request(); 
} 
//真实角色:实现了Subject的request()方法。 
public class RealSubject implements Subject{ 
    public void request() { 
        System.out.println("我是真是角色"); 
    } 
} 
//代理角色: 
public class ProxySubject implements Subject{ 
    //以真实角色作为代理角色的属性 
    private RealSubject realSubject; 

    public ProxySubject(RealSubject real){
        this.realSubject=real;
    }
    //该方法改变了真是对象的request行为
    public void request(){ 
        System.out.println("之前设置新行为" ); 
        realSubject.request(); //此处执行真实对象的request方法 
        System.out.println("之后设置新行为" ); 
    } 
} 
//main测试 
Subject sub=new ProxySubject(); 
Sub.request(); 

 

从上面的代码可以看出,我们可以通过建立代理角色ProxySubject来改变真实角色中的request方法功能(在原方法前后添加些功能)。这个应用非常的广泛,大家可以想想Struts2框架中拦截器在Action执行前所做的工作。但事实上Struts2框架是如何做到这一点的却是十分的复杂,我们需要往下看。
 
我们进一步想一下,当我们知道了抽象角色Subject的具体定义(request方法)的时候,我们当然可以很方便的通过包装Subject的真实角色RealSubject来定义一个能够部分改变真实角色行为的代理角色ProxySubject。但是很多情况下,我们事先并不知道需要代理的对象到底是什么类型的。或者说,只有在运行过程中才知道具体的对象。那么我们能否定义

一种具体行为的代理类,能够动态的实例化任何类型的代理对象呢?说白了,我们就是想做到下面这件事:
 
      定义一种具体行为的代理类型:
            public class ProxySubject implements interfaceX{
                  private ClassX obj;
    public ProxySubject(ClassX obj){
                       this.obj=obj;
                  }
                  public void methodX(){
                       ....新增行为
                       obj.methodx();//真实对象行为
                       ....新增行为
                  }
            }
      运行时遇到不同类型的对象,都能够使用ProxySubject代理来完成新的行为:
            ClassA oa=....
            new ProxySubject(oa).methodX;
            ClassA ob=....
            new ProxySubject(oa).methodX;

 

做到这一点是很困难的,但并非不可能,Java的代理机制就能够帮助我们完成这件事。

 

Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
(1) InvocationHandler接口,是代理实例的调用处理程序实现的接口。 它只有一个方法:invoke(Object proxy, Method method, Object[] args)。我们需要在实现InvocationHandler接口的具体类中的invoke方法内,编写代理行为的具体逻辑。然后将这个InvocationHandler对象传递给Proxy类中生成一个动态的代理对象。

(2) Proxy 类,提供用于创建动态代理类和实例的静态方法。其最重要的两个静态创建方法:
        Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
        Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

 

以上面的代码为例,编写一个动态代理类:

//完成代理行为
import java.lang.reflect.Method;   
import java.lang.reflect.InvocationHandler;   
public class DynamicSubject implements InvocationHandler {   
    private Object sub; //被代理类   
    public DynamicSubject(Object obj) {   
        sub = obj;   
    }   
    //无论何时调用代理类的方法,都会执行这个invoke方法的。
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
        System.out.println("调用被代理对象的方法是:"+method.getName()+"  "+method.getDeclaringClass());
        System.out.println("之前设置新行为" );     
        method.invoke(sub,args); //动态调用被代理类的行为方法。
        System.out.println("之后设置新行为" );  
        return null;   
    }   
}  

//测试
import java.lang.reflect.InvocationHandler;   
import java.lang.reflect.Proxy;   
import java.lang.reflect.Constructor;   
import java.lang.reflect.Method;  
import java.io.*; 

static public void main(String[] args) throws Throwable{
  
    	Object real=new RealSubject(); //被代理对象
	InvocationHandler handler = new DynamicSubject(real); //生成一个具体的代理行为
	Object proxyed = Proxy.newProxyInstance(real.getClass().getClassLoader(), real.getClass().getInterfaces(),handler); //动态生成实现Subject接口的代理类

对象
        if(proxyed instanceof Subject){
                Subject subProx=(Subject)proxyed;
        	subProx.request();
        }
        else proxyed.toString();  
}  
/*
调用被代理对象的方法是:request  interface hr.login.Subject
之前设置新行为
我是真是角色
之后设置新行为
*/

 

分享到:
评论
3 楼 rain2005 2009-09-11  
使用ArrayList在于随机获取数据比较快,我到觉得一般的java应用都可以使用linkedList应该比较高效。
2 楼 weiqingfei 2009-09-10  
C的时候不就是这样干的么
1 楼 leisure 2009-09-10  
所以考虑性能问题,在ArrayList初始化的时候就应该指定合适大小减少数据转移次数

相关推荐

    最新版的Java-解惑

    9. **反射**:Java反射允许在运行时检查类的信息并动态调用方法,是许多高级功能(如ORM框架、动态代理等)的基础。 10. **Lambda表达式和函数式编程**:Java 8引入了lambda表达式,简化了匿名内部类的使用,使得...

    4,JAVA解惑 高清PDF 下载

    除此之外,书中的高级话题如反射、动态代理和Java虚拟机(JVM)的工作原理,也是许多Java开发者关注的重点。理解这些内容可以让你更好地优化代码,提高程序的运行效率,并为进行性能调优打下基础。 《JAVA解惑》...

    Java解惑(中文).pdf

    《Java解惑(中文)》是一本专门为Java开发者编写的指南书籍,旨在解决在实际编程过程中遇到的各种疑惑和难题。本书以中文语言呈现,使得国内的Java程序员能够更轻松地理解并应用其中的知识。通过阅读这本书,读者...

    Java解惑(整理版本)

    《Java解惑(整理版本)》是一篇针对Java编程语言常见问题和疑惑的详细解析文章。博主通过深入探讨Java源码和使用工具的角度,帮助开发者解决实际开发中遇到的问题。以下将围绕标题和描述中的知识点进行展开: 1. *...

    Java解惑(中文版)

    6. **反射与动态代理**:反射机制允许在运行时检查类、接口、字段和方法,而动态代理则能实现动态创建代理对象,这两者在Java中有着广泛的应用。 7. **泛型**:泛型提高了代码的类型安全性和重用性,书中可能详细...

    JAVA解惑.rar

    7. **反射API**:Java反射机制允许我们在运行时检查类、接口、字段和方法的信息,甚至动态调用方法,这是许多高级功能如插件系统、序列化、动态代理的基础。 8. **泛型**:泛型是Java 5引入的新特性,用于提供类型...

    JAVA面试题解惑系列.rar

    Java面试题解惑系列主要涵盖了Java编程语言的核心概念、进阶技术以及在面试中常见的问题。这个压缩包可能包含了两本书籍,一本是"JAVA面试题解惑系列.pdf",另一本是"臧圩人--JAVA面试题解惑系列合集.pdf"。这些资源...

    Java解惑(中文版)

    5. **反射与动态代理**:Java反射机制允许在运行时检查和修改程序行为,这可能导致一些不寻常的问题,而动态代理则涉及接口实现的动态生成,两者都是高级话题,可能包含在书中。 6. **集合框架**:Java集合框架包括...

    Java面试解惑系列

    Java面试解惑系列是针对Java开发者在求职过程中可能遇到的各种面试问题进行深入解析的一个专题。这一系列的内容旨在帮助程序员们更好地理解和掌握Java编程的核心概念、技术细节以及常见误区,从而在面试中展现出扎实...

    Java解惑(帮你深入地了解Java)

    "Java解惑"的主题旨在帮助开发者解决在学习和实践中遇到的复杂问题,加深对Java的理解。下面将详细探讨一些常见的Java知识点,以解答可能出现的疑惑。 1. **内存管理与垃圾回收**:Java通过自动垃圾回收机制管理...

    Java解惑

    《Java解惑》这本书无疑是为Java开发者量身打造的一本技术宝典,它涵盖了Java编程中的常见问题和难点,旨在帮助读者解决实际开发过程中遇到的困惑。书中可能涉及了类与对象、内存管理、多线程、异常处理、集合框架、...

    Java解惑(中文)

    《Java解惑》一书是为Java初学者和进阶者提供的一份宝贵参考资料,它旨在解答在Java编程过程中常见的困惑和难题。本书涵盖了Java语言的核心概念、语法特性以及实战应用,帮助读者深入理解Java编程的本质,提升编程...

    JAVA解惑.大全和问题解析

    "JAVA解惑.大全和问题解析"这个资源就是针对这些问题提供的一份详尽的解答指南。它涵盖了Java的基础知识、常见疑惑点以及易错知识点,旨在帮助Java初学者和进阶者解决实际编程中的困扰。 1. **基础概念解析**: - ...

    JAVA面试题解惑系列

    在"JAVA面试题解惑系列"中,我们深入探讨了Java编程语言在面试中的关键知识点。这个系列旨在帮助Java开发者理解和解决那些在面试过程中可能遇到的棘手问题,揭示一些容易被忽视但至关重要的技术细节。以下是一些核心...

    JAVA解惑 pdf

    《JAVA解惑》这本书是Java编程领域的一本经典读物,以其深入浅出的方式解析了Java编程中的重点和难点。本书旨在帮助Java开发者解决实际编程过程中遇到的问题,提升编程技能和解决问题的能力。以下是对书中一些关键...

    JAVA面试题解惑系列.zip

    "JAVA面试题解惑系列"针对这一需求提供了全面的试题集,旨在帮助求职者深入理解Java语言的关键概念,提高面试成功率。这份资料可能包含了许多Java基础、进阶、设计模式、并发编程、JVM内存管理等方面的问题与解答。 ...

    JAVA面试题解惑系列 (我感觉还是有用的)

    Java面试题解惑系列是为准备Java面试的开发者量身打造的一份宝贵资源,它涵盖了Java编程语言的基础、进阶以及实战应用等多个方面。在这个系列中,你可以找到一系列常见的面试问题,这些问题通常用来评估候选人的编程...

Global site tag (gtag.js) - Google Analytics