Java 代理
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
静态代理
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。
实现步骤:
- 定义一个接口及其实现类;
- 创建一个代理类同样实现这个接口;
- 将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。
接口:
目标对象:
代理对象:
动态代理
动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
JDK 动态代理机制
在 Java 动态代理机制中 InvocationHandler 接口和 Proxy 类是核心。
InvocationHandler接口
InvocationHandler 接口:表示你的代理要干什么。
步骤:
- 创建类实现接口InvocationHandler
- 重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。
Proxy类
Proxy类:创建代理对象。用Proxy类的方法,代替new的使用来创建代理对象。
动态代理创建步骤:
- 先创建拥有目标类要完成功能的接口
- 再创建目标类的实现接口
- 然后再创建InvocationHandler接口的实现类
- 最后再使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。
CGLIB
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。
CGLIB 动态代理机制
在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。
CGLIB 动态代理类步骤
- 先定义一个类;
- 再自定义 MethodInterceptor 接口并重写 intercept 方法,intercept 用于拦截增强被代理类的方法,和 JDK 动态代理中的 invoke 方法类似;
- 最后使用 Enhancer 类中的 create()创建代理对象;
静态代理和动态代理的对比
- 动态代理比静态代理要灵活,可以直接代理实现类不需要实现接口,而且不需要对目标类特定的创建一个代理类。
- JVM 层面 :静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。而动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。