代理

来源:互联网 发布:焓湿图计算软件 编辑:程序博客网 时间:2024/06/07 23:31

代理类可以在运行时创建全新的类,这样的代理类能够实现指定的接口,尤其是他具有下列方法

1.指定接口所需要的全部方法

2.object类中的全部方法比如tostring,equals等

所有的代理类都覆盖了object类中的tostring,equals和hashcode,如果代理对象被调用这些方法,那么也是会被重新定向到调用处理器里面的invoke方法中的。

如果使用同一个类加载器和接口数组调用两次newProxyInstance方法的话,那么只能够得到同一个类的两个对象,也可以利用getProxyClass方法获得这个类, class proxyClass = Proxy.getProxyClass(null,interfaces[]);

代理类一定是public和final,如果代理类实现所有的接口都是public,代理类就不属于某个特定的包,否则所有非公有的接口都必须属于同一个包,同事代理类也属于这个包。可以通过是有那个Proxy类中的isProxyClass方法检测一个特定的CLASS对象是否是一个代理类。

 

如果一个类的某一方法我们需要修改其行为, 如数据库连接池中Connection.close()方法, 并不是真正的去关闭连接, 而只是把这个连接放入连接池里, 所以我们需要拦截这个方法的原来行为, 更改为只是放入连接池. 可以简单的继承java.sql.Connection, 然后实现所有方法, 但只更改close()的行为. 这样做很容易理解, 但是如果一个类的方法太多, 做起来工作量可能会很大. 

另一种方法就是使用动态代理类来实现: Proxy, InvocationHandler. 

import java.util.*;

import java.lang.reflect.*;

 

public class Test01 {

 

public static void main(String[] args) {

MyInvocationHandler mih = new MyInvocationHandler();

MyClass mc = new MyClass();

// 当调用mi的方法时, 如果是要特殊处理的就特殊处理, 否则就调用他对应的那个对象(mc)的方法.

MyInterface mi = mih.bind(mc);

mi.fight();

System.out.println(mi.toString());

}

}

 

interface MyInterface {

void fight();

}

 

class MyClass implements MyInterface {

public void fight() {

System.out.println("Orz, fighting.....");

}

@Override

public String toString() {

return "Hello";

}

}

 

class MyInvocationHandler implements InvocationHandler {

MyClass mc;

MyInterface mi;

 

public MyInterface bind(MyClass mc) {

this.mc = mc;

this.mi = (MyInterface) Proxy.newProxyInstance(MyInterface.class

.getClassLoader(), new Class[] { MyInterface.class }, this);

return mi;

}

 

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

throws Throwable {

// 当调用mi(即proxy)的方法时, 如果是要特殊处理的就特殊处理, 否则就调用他对应的那个对象(mc)的方法.

if ("fight".equals(method.getName())) {

System.out.println("XXXXXXXXXXXXXXXX");

return null;

} else {

return method.invoke(mc, args);

}

}

}

原创粉丝点击