动态代理为执行某个对象的某些方法前(比如A对象的方法a),插入其他操作(方法b)提供了解决方法。而A对象对与加入的方法b并不知情。典型的应用比如Spring的AOP的实现。
以下例子是来自java编程思想P338,个人的理解,若发现有错误的地方希望能指出来。
package com.shine.DynamicProxy;
//: typeinfo/SimpleProxyDemo.java
import java.lang.reflect.*;
//动态代理需要一个接口
interface Interface {
void doSomething();
void somethingElse(String arg);
}
//一个实现接口的类
class RealObject implements Interface {
/*5B*/ public void doSomething() { System.out.println("doSomething"); }
public void somethingElse(String arg) {
System.out.println("somethingElse " + arg);
}
}
/*定义调用处理器DynamicProxyHandler,该处理器实现InvocationHandler接口。
* 所有对动态代理的操作都会被转到DynamicProxyHandler中的invoke方法,可以在invoke()
* 中定义需要被插入的操作*/
class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
/*4*/public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*此处定义插入的操作,然后再由method.invoke(proxied, args)将
* 请求转发给被代理的对象,并传入需要的参数*/
System.out.println("**** proxy: " + proxy.getClass() +
", method: " + method + ", args: " + args);
if(args != null)
for(Object arg : args)
System.out.println(" " + arg);
/*5A*/ return method.invoke(proxied, args);
}
}
public class SimpleDynamicProxy {
public static void consumer(Interface iface) {
/*3*/iface.doSomething();
iface.somethingElse("bonobo");
}
public static void main(String[] args) {
RealObject real = new RealObject();
consumer(real);
// Insert a proxy and call again:
/*创建动态代理对象,newProxyInstance()的参数包括
* 类加载器,你希望该代理实现的接口列表,InvocationHandler接口的实现*/
/*1*/Interface proxy = (Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[]{ Interface.class },
new DynamicProxyHandler(real));
/*2*/consumer(proxy);
}
}
/* Output: (95% match)
doSomething
somethingElse bonobo
**** proxy: class $Proxy0, method: public abstract void Interface.doSomething(), args: null
doSomething
**** proxy: class $Proxy0, method: public abstract void Interface.somethingElse(java.lang.String), args: [Ljava.lang.Object;@42e816
bonobo
somethingElse bonobo
*///:~
**** proxy: class $Proxy0, method: public abstract void Interface.doSomething(), args: null
doSomething
为例说明程序的运行顺序;
1->2->3->4->5A->5B
1:生成动态代理对象,包含被代理对象的信息;
2:普通的调用函数;
3:动态代理对象所调用的所有方法均会被重定向到调用处理器DynamicProxyHandler的invoke(...)方法;
4:在invoke(...)方法中添加需要插入的操作,比如输出**** proxy: class $Proxy0, method: public abstract void Interface.doSomething(), args: null
5A:由method.invoke(proxied, args)将请求转发给被代理对象,并传入必须的参数;
5B:被代理对象调用函数,输出 doSomething