您的位置:首页 > 编程语言 > Java开发

java动态代理Proxy类的理解

2011-08-15 01:55 330 查看
在Java中利用代理(Proxy)可以在运行时创建一个实现了一组给定接口的新类。
在系统程序设计中,有时需要面对无法确定接口,却需要构造对象的情况。以前为了解决此问题,有些程序根据动态确定的接口,生成Java类文件,然后调用类加载器构造该对象,然后使用,这样一来无可避免性能问题。通过代理类,能够在不额外创建Java文件的情况下构造对象及调用该对象方法。

使用代理的理由有很多,其中就有如下的情况:

1.路由对远程服务器的方法调用

2.在程序运行期间,将用户接口事件与行动关联起来

3.调试时跟踪方法调用

以下举出一例,使用代理和调用处理器跟踪方法调用

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Random;

public class ProxyTest
{
public static void main(String[] args)
{
Object[] elements = new Object[1000];

// fill elements with proxies for the integers 1  1000
for (int i = 0; i < elements.length; i++)
{
Integer value = i + 1;
Class[] interfaces = value.getClass().getInterfaces();
InvocationHandler handler = new TraceHandler(value);
Object proxy = Proxy.newProxyInstance(null,
interfaces, handler);
elements[i] = proxy;
}

// construct a random integer
Integer key = new Random().nextInt(elements.length) + 1;

// search for the key
int result = Arrays.binarySearch(elements, key);

// print match if found
if (result >= 0) System.out.println(elements[result]);
}
}

/**
An invocation handler that prints out the method name
and parameters, then invokes the original method
*/
class TraceHandler implements InvocationHandler
{
/**
Constructs a TraceHandler
@param t the implicit parameter of the method call
*/
public TraceHandler(Object t)
{
target = t;
}

public Object invoke(Object proxy, Method m, Object[] args) throws Throwable//此方法在代理类中的方法被调用时均会被调用
{ // print implicit argument
System.out.print(target);
// print method name
System.out.print("." + m.getName() + "(");
// print explicit arguments
if (args != null)
{
for (int i = 0; i < args.length; i++)
{
System.out.print(args[i]);
if (i < args.length - 1)
System.out.print(", ");
}
}
System.out.println(")");

// invoke actual method
//      return new Integer("123");
return m.invoke(target, args);
}

private Object target;
}


在此处,代理类取代了可能需要额外创建的Java文件。
当调用代理类的方法时,调用实现InvocationHandler接口的方法invoke,此时可以针对传入参数Method的不同,定义不同的方法体(操作)

Proxy类的特性:

1.代理(Proxy)类只有一个实例变量,即调用处理器(InvocationHandler)

2.代理类需要的额外数据都必须存储在调用处理器中

3.代理类一定是public和final.

4.如果代理类实现的所有接口都是public,则代理类就不属于某个特定的包;否则所有的非公有接口都必须属于同一个包,代理类也属于这个包(此设定的目的是确定代理类的所属包)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: