简单的说,有A类,现在希望在A类的函数print()中增加Log类的功能log(),但是不能修改A类源码,因为用户手中只有A类的.class文件,于是提供了动态代理的方法,即新建一个动态代理类A_proxy继承A类,同时新建一个处理类InLog继承InvocationHandler, 然后重写InLog的invoke函数,首先增加log()的功能,然后调用method.invoke()激发print()函数,实际执行的时候,
A a = (A)Proxy.newProxyInstance(
getClass().getClassLoader(), // 1. 类加载器
new Class<?>[] {A.class}, // 2. 代理需要实现的接口,可以有多个
new InLog(new A_proxy()));
然后调用的时候执行a.print()即可
注意以下问题:
1. a 的实际类型是jdkproxy.$Proxy* ,是动态生成的。
2. 对代理对象a的所有.print()函数调用,最终都会被转发到InvocationHandler.invoke()并执行内部逻辑.
通过以上方式,对原有print()函数的功能增加需求就被转移到了A_proxy这个代理类中,用户使用的时候只需要在创建
对象时执行:
A a = (A)Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] {A.class}, new InLog(new A_proxy()));
则生成的a对象就增加了日志的功能,而a的实际类型A_proxy又是动态生成的,
讲白了,同多态这种静态代理的方式不同,多态实现的时候,子类在编译期即被加载,
动态代理虽然也是通过接口实现不同类和对象之间的运行,但是指针指向的类并不是编译时决定的,而是实际执行时生成的类和对象,该对象拦截了执行的方法,并调用了InvocationHandler.invoke()里面的处理逻辑,就相当于把A_proxy的print()调用代理到了InvocationHandler中,因此称之为动态代理。
参考:http://www.importnew.com/27772.html