0x01 前言
JDK动态代理与Cglib代理的区别
JDK 动态代理:
拦截器实现InvocationHandler接口,加上反射机制生成一个实现代理接口的匿名类
在调用具体方法前调用InvokeHandler来处理,自身额外操作
Cglib代理:
利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理
JDK动态代理与Cglib字节码生成的区别?
JDK动态代理只能对实现了接口的类生成代理,而不能针对类
Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的
0x02 环境
编辑器为: IntelliJ IDEAjava版本:java version "1.8.0_271"Java(TM) SE Runtime Environment (build 1.8.0_271-b09)Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)使用的架包:cglib 3.3.0代码仓库: https://github.com/pmiaowu/JavaProxyTest
0x03 语法介绍
0x03.1 MethodInterceptor接口
package net.sf.cglib.proxy;import java.lang.reflect.Method;public interface MethodInterceptor extends Callback {/*** @param var1 被代理的对象* @param var2 被代理对象的方法* @param var3 参数集合* @param var4 生成的代理类* @return* @throws Throwable*/Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;}
0x04 例子
例如现在有一个人,想去影院看电影,看完电影顺便去上个厕所
但是我们作为电影院的人,还想产生一些额外的收益
比如在影片开始与结束时播发一些广告
或是去洗手间的时候播发一些广告
先建立个人的行为类
package 动态代理2;public class People {public void movie() {System.out.println("您正在观看电影《花园宝宝历险记》");}public void toilet() {System.out.println("您冲进了洗手间");}}
在建立个电影院提供用户最爱的广告
package 动态代理2;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class Cinema implements MethodInterceptor {private Object target;public Object bind(Object target) {this.target = target;// 工具类Enhancer en = new Enhancer();// 设置父类en.setSuperclass(target.getClass());// 设置回调函数en.setCallback(this);// 创建子类代理对象return en.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(" ");System.out.println("------------------");System.out.println("该影院叫: " + this.getClass().getSimpleName());this.advertising1();Object obj = method.invoke(this.target);this.advertising2();return obj;}public void advertising1() {System.out.println("开始广告: 电影准备开始了,肯德基十翅一桶,只需要39元,快来买啊!");}public void advertising2() {System.out.println("结束广告: 电影结束了,肯德基十翅一桶,只需要39元,快买回家吃吧!");}}
运行看看结果
package 动态代理2;public class Test {public static void main(String[] args) {People people = new People();Cinema cinema = new Cinema();People peopleProxy = (People) cinema.bind(people);peopleProxy.movie();peopleProxy.toilet();}}// 执行结果------------------该影院叫: Cinema开始广告: 电影准备开始了,肯德基十翅一桶,只需要39元,快来买啊!您正在观看电影《花园宝宝历险记》结束广告: 电影结束了,肯德基十翅一桶,只需要39元,快买回家吃吧!------------------该影院叫: Cinema开始广告: 电影准备开始了,肯德基十翅一桶,只需要39元,快来买啊!您冲进了洗手间结束广告: 电影结束了,肯德基十翅一桶,只需要39元,快买回家吃吧!
