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

Java的代理机制

2022-02-06 15:19 721 查看

Java的代理机制

使用代理 Proxzy 可以在运行时创建一组给定接口的新类,这种功能只有在编译时无法确定需要实现哪种接口时才需要使用。

1. 使用代理的时机

假如有一个表示接口的 Class 对象,它的确切类型在编译时无法得知。由于没有实现类而只有一个接口,反射和

newInstance
语句是无法实例化这个 Class 对象的,我们需要在程序处于运行状态时定义一个新类。

代理类可以在运行时创建全新的类,这样的代理类可以实现指定的接口,它具有下列方法:

  • 指定接口所需要的全部方法。
  • Object 类中的全部方法,例如
    toString()
    equals()
    等。

在代理机制中,不能再允许时定义这些方法的新代码,而是要提供一个调用处理器 InvocationHandler调用处理器是实现了

InvocationHandler
接口的类对象。在这个接口中只有一个方法:

Object invoke(Object proxy, Method method, Object[] args)

无论何时调用代理对象的方法,

invoke()
方法都被调用,并向其传递 Method 对象和原始的调用参数,调用处理器必须给出处理调用的方式。

2. 创建代理对象

创建代理对象要使用 Proxy 类的

newProxyInstance
方法,这个方法有三个参数:

  • 一个类加载器。可以使用不同的类加载器,用 null 表示使用默认的类加载器。
  • 一个 Class 对象数组。每个元素都是需要实现的接口。
  • 一个调用处理器。

下面给出一个示例程序,使用代理和调用处理跟踪方法调用:

// 调用处理器
class TraceHandler implements InvocationHandler{
private Object target;

// 构造函数
public TraceHandler(Object t){
target = t;
}

// invoke方法
public Object invoke(Objcet proxy, Method m, Object[] args) throws Throwable {
// print method name and parameters
...
// invoke actual method
return m.invoke(target, args);
}
}

下面的代码,我们用于跟踪方法调用的代理对象:

Object value = ...;
// 构造调用处理器
InvocationHandler handler = new TraceHandler(value);
// 构造代理对象
Class[] interfaces = new Class[](Comparable.class);
Object proxy = Proxy.newProxyInstance(null, interfaces, handler);

我们再用 proxy 任何方法时,都会调用

invoke()
方法,打印出方法的名字和参数,再用
value
对象调用它。

3. 代理类的特性

代理类有下面这样一些特性:

  • 所有的代理类都扩展于 Proxy 类。一个代理类只有一个实例域:调用处理器。
  • 所需的任何附加数据存储在调用处理器中,例如代理 Comparable 对象时,在
    TraceHandler
    中包装了实际的对象
    target
  • 所有的代理类都覆盖了 Object 类中的方法
    toString()
    equals()
    hashCode()
    。如果所有的代理方法一样,这些方法仅仅调用了调用处理器的
    invoke()
    。Object 类中的其他方法没有被重新定义。
  • 对于特定的类加载器和一组预设的接口,最多只能有一个代理类。也就是说如果用同样的参数重复调用两次
    newProxyInstance()
    方法,那么只能得到一个类的两个对象。
  • 代理类一定是 public、final 。如果代理类实现的所有接口都是 public 的,代理类就不属于某个特定的包。否则所有非公有的接口必须属于同一个包,代理类也属于这个包。
  • 可以用 Proxy 类的
    isProxyClass()
    方法检测一个特定的 Class 对象是否是一个代理类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: