概述
代理是设计模式的一种,设计模式是指调用者并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。代理类与真正实现的类都是继承或者实现一个相同的类或这接口,这样的好处在于代理类可以与实际的类有相同的方法,可以保证客户端使用的透明性。
既然有动态代理,那么相对应的肯定也存在静态代理。
- 静态代理:由程序员手工编写代理类。
- 动态代理:在程序运行时运用反射机制动态创建生成代理类。
静态代理略去不介绍,下面介绍一下动态代理的实现。我们可以使用JDK的 InvocationHandler 和 Proxy 实现,也可以通过 CGLIB 来实现,他们的区别后面介绍,这里之介绍 InvocationHandler 和 Proxy 的实现。
动态代理
Java的动态代理主要涉及两个类,Proxy
和 InvocationHandler
。
Proxy
用于为接口生成动态代理类及其对象。InvocationHandler
提供了invoke
方法,负责集中处理动态代理类上的所有方法调用。
代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。
下面通过一个实例来演示一下:
1 | public interface Fruit { |
1 | public class Apple implements Fruit { |
1 | public static void testProxy(){ |
结果:
1 | E/Test: Let Apple introduce himself. |
实现动态代理的方法:
- 获取需要代理的类的实例。
- 实现 InvocationHandler 接口创建自己的调用处理器,实现 invoke 方法,通过
method.invoke(apple, args)
调用被代理类。 - 通过 Proxy.newProxyInstance 方法并指定 ClassLoader 对象和一组 interface 以及 指定 invocationHandler 对象来创建动态代理类。
- 通过反射机制获得动态代理类的构造函数。
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
其中 Proxy.newProxyInstance()
方法封装了 3~5 步骤的实现。下面一节将会简单介绍它的原理。
动态代理原理
下来看一下 Proxy.newProxyInstance()
源码。
1 | public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, |
来看一下 Proxy.getProxyClass()
这个方法:
1 | public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) |
小结
Proxy 虽然使用起来很方便,但它的设计使得它只能支持 interface 的代理,Java 的继承机制注定了动态代理类无法实现对 class 的动态代理,因为多继承在 Java 中本质上就行不通。因为代理类需要继承 Proxy 类,这样它就不能再继承其他的类了。因此不支持实现类的代理,只支持接口的代理。
但是目前也有了针对 class 的动态代理解决方案,比如 CGLib。
相关推荐文章
https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/
http://blog.csdn.net/chjttony/article/details/7934776
http://blog.csdn.net/rock_ray/article/details/22491763
http://rejoy.iteye.com/blog/1627405
http://www.cnblogs.com/xiaoluo501395377/p/3383130.html