[toc]
动态代理模式
定义
相比 静态代理,动态代理具有更强的 灵活性,因为它不用在我们设计实现的时候就指定 某一个代理类来代理哪一个被代理对象,我们可以把这种指定延迟到程序运行时由 JVM来实现。
类图
实例
动态代理类:在该类中需要指定需要传入被代理类的对象。
需要被代理的真实的类:
public class RealSubject implements Subject{ @Override public void request() { System.out.println("real subject request"); } }
client:先创建一个代理类。然后利用反射创建一个用真实类加载器创建的一个对象。该对象调用request方法实际上调用的是代理类的invoke
方法。
和静态代理模式比较的好处
在静态代理模式时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;而动态
源码分析
参考:http://rejoy.iteye.com/blog/1627405 主要原来:生成了一个代理类的class文件。 Proxy.newProInstance()方法
其中newInstance只是调用Constructor.newInstance来构造相应的代理类实例,这里重点是看getProxyClass0这个方法的实现:
其中代理缓存是使用WeakCache实现的,如下
具体的缓存逻辑这里暂不关心,只需要关心ProxyClassFactory是如何生成代理类的,ProxyClassFactory是Proxy的一个静态内部类,实现了WeakCache的内部接口BiFunction的apply方法:
ProxyGenerator是sun.misc包中的类,它没有开源,但是可以反编译来一探究竟:
saveGeneratedFiles这个属性的值从哪里来呢:
GetBooleanAction
实际上是调用Boolean.getBoolean(propName)
来获得的,而Boolean.getBoolean(propName)
调用了System.getProperty(name)
,所以我们可以设置sun.misc.ProxyGenerator.saveGeneratedFiles
这个系统属性为true来把生成的class保存到本地文件来查看。
反编译class文件
自己创建文件写入
OK接下来,我们在客户端代码中设置这个值:
运行之后发现报错,报错信息如下:报错原因是因为,我们要在运行当前main方法的路径下创建com/sun/proxy
目录,并创建一个$Proxy0.class文件,才能够正常运行并保存
class`文件内容。
注意: 这个文件的路径为:System.getProperty("user.dir")+File.separator+该接口的包路径 for:/Users/nemo/03ws/sp_intel/com/sun/proxy
直接调用API进行源码 byte写入文件
在上面,我们需要手动穿件一个$Proxy0.class文件让系统写入。当然我们可以调用API直接写入到任何文件中。 参考:[http://rejoy.iteye.com/blog/1627405]http://rejoy.iteye.com/blog/1627405
工具类:
import java.io.FileOutputStream; import java.io.IOException;
import sun.misc.ProxyGenerator;
/
* 代理类的生成工具
* @author zyb
* @since 2012-8-9
*/
public class ProxyGeneratorUtils {
/
* 把代理类的字节码写到硬盘上
* @param path 保存路径
*/
public static void writeProxyClassToHardDisk(String path) {
// 第一种方法,这种方式在刚才分析ProxyGenerator时已经知道了
// System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true);
// 第二种方法
// 获取代理类的字节码
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", UserServiceImpl.class.getInterfaces());
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package dynamic.proxy;
import org.junit.Test;
/*
* 动态代理测试类
* @author zyb
* @since 2012-8-9
*
/
public class ProxyTest {
@Test
public void testProxy() throws Throwable {
// 实例化目标对象
UserService userService = new UserServiceImpl();
// 实例化InvocationHandler
MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
// 根据目标对象生成代理对象
UserService proxy = (UserService) invocationHandler.getProxy();
// 调用代理对象的方法
proxy.add();
<span class="o">}</span>
@Test public void testGenerateProxyClass() { ProxyGeneratorUtils.writeProxyClassToHardDisk("F:/$Proxy11.class"); } }
最后:反编译之后的源码如下
import com.nemo.design.dynamicproxy.Subject; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Subject { private static Method m1; private static Method m3; private static Method m0; private static Method m2;
public $Proxy0(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); }
public final boolean equals(Object paramObject) throws { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
public final void request() throws { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
public final int hashCode() throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
public final String toString() throws { try { return (String)this.h.invoke(this, m2, null); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("com.nemo.design.dynamicproxy.Subject").getMethod("request", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } }