Java SE之旅_09_代理Proxy

来源:互联网 发布:修改ex软件图标 编辑:程序博客网 时间:2024/06/18 10:26

在Java中,如何在不修改一个类的情况下对该类特定的方法执行特殊的任务呢?

Java提供了代理类Proxy来解决这种问题. 前提条件是被代理对象必须至少实现一个接口.


Proxy提供了静态方法newProxyInstance以创建代理对象,具体方法如下:

java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 

其中,第一个参数loader指定运行类的类加载器,第二个参数指定被代理的对象实现的所有接口,第三个是InvocationHandler 接口,必须实现invoke方法以对被代理对象的方法进行拦截.


下面是个使用代理的小例子.

1. 定义一个接口MyInterface, 该接口有两个未实现的方法:

public interface MyInterface {void sayHi(String name);boolean close(); }

2. 定义接口MyInterface的实现类MyInterfaceImpl:

public class MyInterfaceImpl implements MyInterface {@Overridepublic void sayHi(String name) {System.out.println("hi! your name is: " + name);System.out.println();}@Overridepublic boolean close() {System.out.println("the method close() is running...");return true;}}

3. 定义测试类,使用Proxy对被代理对象obj进行代理,拦截在obj上执行的所有方法:

public class ProxyDemo {public static void main(String[] args) {//创建被代理对象objfinal Object obj = new MyInterfaceImpl();//创建代理者,代理objObject proxy = Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(), // 指定该测试类的类加载器// 被代理的对象实现的所有接口,此处只有MyInterface这个接口new Class[]{MyInterface.class}, new InvocationHandler(){//执行方法的句柄,是一个接口,只有一个方法invoke//invoke方法拦截所有在被代理对象obj上执行的方法,包括参数public Object invoke(Object proxy,Method method, Object[] args)throws Throwable {System.out.println("method's name = "+method.getName());//拦截参数if(null != args){System.out.println("args[0] is : " + args[0].toString());}else{System.out.println("no args... ");}//拦截方法if("close".equals(method.getName())){System.out.println("********** 拦截到close方法,测试一下不执行该方法**********");return false;}else{//把参数args传给obj,通过反射调用obj的method方法return method.invoke(obj, args);}} }); //将代理者强转成MyInterface,调用MyInterface定义的方法进行测试MyInterface impl = (MyInterface)proxy;impl.sayHi("小明");impl.close();}}


运行结果:



在测试中,当执行句柄InvocationHandler的invoke方法拦截到impl的close方法时, 不执行close方法, 做到了在不修改原类MyInterfaceImpl的情况下对MyInterfaceImpl的close方法进行特殊处理, 这就是传说中的动态代理~~

当然,你也可以重新写个类继承MyInterfaceImpl,重写close方法,但是这样做会产生不少"没多大用途"的类,它们的职责只是为了修改一个方法... 而是用代理就比较灵活,体现了Java语言的动态代理机制.

0 0