关键词:动态代理 CGLIB Callback
关于JDK动态代理,请看《JDK动态代理》。
CGLIB动态代理的核心类是:net.sf.cglib.proxy.Enhancer,Enhancer主要完成代理对象创建的过程。
Callback接口没有定义方法,它有如下几种子接口,在子接口中分别对应了不同的方法,以此能够使得代理对象的功能更加丰富,逻辑的增强功能更加强大。可以叫它增强器。
可以通过Enhancer提供的方法setCallback(Callback callback)或setCallbacks(Callback[] callbacks)分别指定一个或多个Callback对象。
需要注意的是一个代理对象的方法被执行时,只会有一个Callback实现逻辑会被调用。所以在使用setCallbacks(Callback[] callbacks)设置多个Callback时,还需要配合使用setCallbackFilter(CallbackFilter filter)方法来指定方法使用的是具体的哪个Callback。如果设置了多个Callback,但没有设置CallbackFilter的话,会报Multiple callback types possible but no filter specified异常。但你会说了,既然每次方法调用只能增强一个Callback逻辑,那设置多个有什么用呢?用处就在于,配合CallbackFilter来使用后,能够让不同的方法被不同的Callback来增强。比如方法1被Callback1增强,方法2被Callback2增强。
CallbackFilter: 当配置了多个Callback时,用于过滤出需要的某个Callback package net.sf.cglib.proxy; import java.lang.reflect.Method; public interface CallbackFilter { int accept(Method var1); boolean equals(Object var1); }比如定义这样的实现类:
public class CallbackFilterImpl implements CallbackFilter { @Override public int accept(Method method) { if ("equals".equals(method.getName())) { return 0; } else if ("hashcode".equals(method.getName())){ return 1; } else { return 2; } } }定义3个Callback实现类,并调用set方法设置,同时也设置CallbackFilter
Callback[] callbacks = new Callback[]{new CallBack01(), new CallBack02(), new CallBack02()}; enhancer.setCallbacks(callbacks); enhancer.setCallbackFilter(new CallbackFilterImpl());实现的功能:若调用代理对象的equals方法,就会使用callback数组中下标为0的Callback实现对象增强逻辑,即CallBack01。同理调用hashcode方法,就会使用数组下标为1的Callback实现类增强逻辑,即Callback02。
需要注意的是,在accept中,返回的结果是Callback数组的下标,若是不合法的数组下标就会抛出异常。比如-1。再比如上面的例子,数组中只有3个元素,若返回大于等于3以上的数字,也会抛出异常,毕竟数组中没有那么多元素。其实使用的过程中,只要数组不越界,返回的整数都是合理的。
Callback的子接口很多,但原理大致相同,这里以MethodInterceptor为例。
①创建接口
此步骤非必须,因为CGLIB可以直接对类生成代理。
public interface Worker { void work(); String workWithResult(); void workWithParam(int param1, String param2); }②创建接口实现类
public class CarWork implements Worker{ @Override public void work() { System.out.println("CarWork work ......"); } @Override public String workWithResult() { return null; } @Override public void workWithParam(int param1, String param2) { } /** * CarWork自定义的方法,不是继承自接口 */ public void custom() { System.out.println("CarWork method"); } }③创建Callback实现类,这里使用的是Callback的一个子接口:MethodInterceptor
public class WorkerCallBack implements MethodInterceptor { // 需要被增强逻辑的对象 private Worker worker; public WorkerCallBack(Worker worker) { this.worker = worker; } // o 生成的代理对象 // method 被调用的方法对象 // objects 方法参数 // methodProxy 方法代理 @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println(method.getName()+"被执行前的增强逻辑"); // 调用实际的对象逻辑 Object result = method.invoke(worker, objects); System.out.println(method.getName()+"被执行后的增强逻辑"); return result; } }④运行
public static void main(String[] args) { Enhancer enhancer = new Enhancer(); /** * 设置代理对象所实现的接口 * java支持实现多个接口,所以这里是数组 * */ enhancer.setInterfaces(new Class[]{Worker.class}); /** * 设置代理对象所继承的类 * java只支持单继承 */ enhancer.setSuperclass(CarWork.class); /** * 设置增强逻辑实现。可以指定多个 */ enhancer.setCallback(new WorkerCallBack(new CarWork())); // 创建代理对象 Worker worker = (Worker)enhancer.create(); // 调用方法 worker.work(); }⑤输出结果
work被执行前的增强逻辑 CarWork work ...... work被执行后的增强逻辑如果你同时熟悉JDK动态代理的话,是不是感觉MethodInterceptor和JDK动态代理中的InvocationHandler差不多。
既然功能差不多,那实现原理是不是也相似呢?下面让我们看看。
查看源代码,从enhancer.create()方法开始,依次查看源码:
create() ——> createHelper() ——> super.create(key) ——> new AbstractClassGenerator.ClassLoaderData(loader) ——> gen.generate(ClassLoaderData.this) ——> byte[] b = this.strategy.generate(this);
看见字节数组byte[] b了,应该就能猜到这个就是代理对象的字节数组了。
下面就来看看byte[] b = this.strategy.generate(this);产生了什么东西吧。
这个方法是在类AbstractClassGenerator中的,this就是AbstractClassGenerator对象。在构造方法中有this.strategy = DefaultGeneratorStrategy.INSTANCE; 而Enhancer又是AbstractClassGenerator的实现类。所以这段代码可以写成:
public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setInterfaces(new Class[]{Worker.class}); enhancer.setSuperclass(CarWork.class); enhancer.setCallback(new WorkerCallBack(new CarWork())); // 这里要加这句,不加会报空指针 enhancer.create(); try { byte[] bytes = DefaultGeneratorStrategy.INSTANCE.generate(enhancer); // 输出到文件 Files.write(new File("D:\\data\\CarWorkProxy.class").toPath(), bytes); } catch (Exception e) { e.printStackTrace(); } }使用IDEA打开生成的文件,内容如下:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import java.lang.reflect.Method; import net.sf.cglib.core.ReflectUtils; import net.sf.cglib.core.Signature; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Factory; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; // 代理类继承了CarWork,实现了Worker接口 // Factory也是一个接口,定义了一些比如获取Callback的方法等等 public class CarWork$$EnhancerByCGLIB$$28a85fd5 extends CarWork implements Worker, Factory { private boolean CGLIB$BOUND; public static Object CGLIB$FACTORY_DATA; private static final ThreadLocal CGLIB$THREAD_CALLBACKS; private static final Callback[] CGLIB$STATIC_CALLBACKS; private MethodInterceptor CGLIB$CALLBACK_0; private static Object CGLIB$CALLBACK_FILTER; private static final Method CGLIB$work$0$Method; private static final MethodProxy CGLIB$work$0$Proxy; private static final Object[] CGLIB$emptyArgs; private static final Method CGLIB$workWithParam$1$Method; private static final MethodProxy CGLIB$workWithParam$1$Proxy; private static final Method CGLIB$workWithResult$2$Method; private static final MethodProxy CGLIB$workWithResult$2$Proxy; private static final Method CGLIB$equals$3$Method; private static final MethodProxy CGLIB$equals$3$Proxy; private static final Method CGLIB$toString$4$Method; private static final MethodProxy CGLIB$toString$4$Proxy; private static final Method CGLIB$hashCode$5$Method; private static final MethodProxy CGLIB$hashCode$5$Proxy; private static final Method CGLIB$clone$6$Method; private static final MethodProxy CGLIB$clone$6$Proxy; static void CGLIB$STATICHOOK2() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; Class var0 = Class.forName("CarWork$$EnhancerByCGLIB$$28a85fd5"); Class var1; Method[] var10000 = ReflectUtils.findMethods(new String[]{"work", "()V", "workWithParam", "(ILjava/lang/String;)V", "workWithResult", "()Ljava/lang/String;"}, (var1 = Class.forName("CarWork")).getDeclaredMethods()); CGLIB$work$0$Method = var10000[0]; CGLIB$work$0$Proxy = MethodProxy.create(var1, var0, "()V", "work", "CGLIB$work$0"); CGLIB$workWithParam$1$Method = var10000[1]; CGLIB$workWithParam$1$Proxy = MethodProxy.create(var1, var0, "(ILjava/lang/String;)V", "workWithParam", "CGLIB$workWithParam$1"); CGLIB$workWithResult$2$Method = var10000[2]; CGLIB$workWithResult$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "workWithResult", "CGLIB$workWithResult$2"); var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods()); CGLIB$equals$3$Method = var10000[0]; CGLIB$equals$3$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$3"); CGLIB$toString$4$Method = var10000[1]; CGLIB$toString$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$4"); CGLIB$hashCode$5$Method = var10000[2]; CGLIB$hashCode$5$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$5"); CGLIB$clone$6$Method = var10000[3]; CGLIB$clone$6$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$6"); } // 这里相当于没有增强逻辑,和直接调用CarWork的work方法效果相同 final void CGLIB$work$0() { super.work(); } // 调用代理对象的work方法,实现对目标对象逻辑的增强 public final void work() { // 获取增强器 MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { // 调用增强器的方法 var10000.intercept(this, CGLIB$work$0$Method, CGLIB$emptyArgs, CGLIB$work$0$Proxy); } else { super.work(); } } final void CGLIB$workWithParam$1(int var1, String var2) { super.workWithParam(var1, var2); } public final void workWithParam(int var1, String var2) { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$workWithParam$1$Method, new Object[]{new Integer(var1), var2}, CGLIB$workWithParam$1$Proxy); } else { super.workWithParam(var1, var2); } } final String CGLIB$workWithResult$2() { return super.workWithResult(); } public final String workWithResult() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$workWithResult$2$Method, CGLIB$emptyArgs, CGLIB$workWithResult$2$Proxy) : super.workWithResult(); } /** *注意这个方法,这个方法是在CarWork中添加的方法,没有继承自接口。但也会被增强。 * */ public final void custom() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$custom$3$Method, CGLIB$emptyArgs, CGLIB$custom$3$Proxy); } else { super.custom(); } } final boolean CGLIB$equals$3(Object var1) { return super.equals(var1); } public final boolean equals(Object var1) { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { Object var2 = var10000.intercept(this, CGLIB$equals$3$Method, new Object[]{var1}, CGLIB$equals$3$Proxy); return var2 == null ? false : (Boolean)var2; } else { return super.equals(var1); } } final String CGLIB$toString$4() { return super.toString(); } public final String toString() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$4$Method, CGLIB$emptyArgs, CGLIB$toString$4$Proxy) : super.toString(); } final int CGLIB$hashCode$5() { return super.hashCode(); } public final int hashCode() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { Object var1 = var10000.intercept(this, CGLIB$hashCode$5$Method, CGLIB$emptyArgs, CGLIB$hashCode$5$Proxy); return var1 == null ? 0 : ((Number)var1).intValue(); } else { return super.hashCode(); } } final Object CGLIB$clone$6() throws CloneNotSupportedException { return super.clone(); } protected final Object clone() throws CloneNotSupportedException { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? var10000.intercept(this, CGLIB$clone$6$Method, CGLIB$emptyArgs, CGLIB$clone$6$Proxy) : super.clone(); } public static MethodProxy CGLIB$findMethodProxy(Signature var0) { String var10000 = var0.toString(); switch(var10000.hashCode()) { case -1228780993: if (var10000.equals("workWithResult()Ljava/lang/String;")) { return CGLIB$workWithResult$2$Proxy; } break; case -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) { return CGLIB$clone$6$Proxy; } break; case 304511822: if (var10000.equals("workWithParam(ILjava/lang/String;)V")) { return CGLIB$workWithParam$1$Proxy; } break; case 1525100228: if (var10000.equals("work()V")) { return CGLIB$work$0$Proxy; } break; case 1826985398: if (var10000.equals("equals(Ljava/lang/Object;)Z")) { return CGLIB$equals$3$Proxy; } break; case 1913648695: if (var10000.equals("toString()Ljava/lang/String;")) { return CGLIB$toString$4$Proxy; } break; case 1984935277: if (var10000.equals("hashCode()I")) { return CGLIB$hashCode$5$Proxy; } } return null; } public CarWork$$EnhancerByCGLIB$$28a85fd5() { CGLIB$BIND_CALLBACKS(this); } public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) { CGLIB$THREAD_CALLBACKS.set(var0); } public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) { CGLIB$STATIC_CALLBACKS = var0; } private static final void CGLIB$BIND_CALLBACKS(Object var0) { CarWork$$EnhancerByCGLIB$$28a85fd5 var1 = (CarWork$$EnhancerByCGLIB$$28a85fd5)var0; if (!var1.CGLIB$BOUND) { var1.CGLIB$BOUND = true; Object var10000 = CGLIB$THREAD_CALLBACKS.get(); if (var10000 == null) { var10000 = CGLIB$STATIC_CALLBACKS; if (var10000 == null) { return; } } var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0]; } } public Object newInstance(Callback[] var1) { CGLIB$SET_THREAD_CALLBACKS(var1); CarWork$$EnhancerByCGLIB$$28a85fd5 var10000 = new CarWork$$EnhancerByCGLIB$$28a85fd5(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Callback var1) { CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1}); CarWork$$EnhancerByCGLIB$$28a85fd5 var10000 = new CarWork$$EnhancerByCGLIB$$28a85fd5(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) { CGLIB$SET_THREAD_CALLBACKS(var3); CarWork$$EnhancerByCGLIB$$28a85fd5 var10000 = new CarWork$$EnhancerByCGLIB$$28a85fd5; switch(var1.length) { case 0: var10000.<init>(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; default: throw new IllegalArgumentException("Constructor not found"); } } public Callback getCallback(int var1) { CGLIB$BIND_CALLBACKS(this); MethodInterceptor var10000; switch(var1) { case 0: var10000 = this.CGLIB$CALLBACK_0; break; default: var10000 = null; } return var10000; } public void setCallback(int var1, Callback var2) { switch(var1) { case 0: this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2; default: } } public Callback[] getCallbacks() { CGLIB$BIND_CALLBACKS(this); return new Callback[]{this.CGLIB$CALLBACK_0}; } public void setCallbacks(Callback[] var1) { this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0]; } static { CGLIB$STATICHOOK2(); } }如果你知道JDK动态代理生成的代理类的内容的话,再看看CGLIB生成的内容,是不是感觉他们实现方式都差不多呢。只是CGLIB生成的代理类内容更多一些,那相应的功能就会丰富。
相信你一定在很多地方看到过这样的一句话:JDK动态代理是针对接口生成的代理,CGLB是针对具体的类生成的代理。其实通过比较JDK动态代理和CGLB动态代理生成的代理类的内容,可以看出:
JDK动态代理产生的代理类 extends Proxy implements Worker 是实现了接口,继承了Proxy类。与需要被增强的接口实现类没有关系。而CGLB动态代理产生的代理类 extends CarWork implements Worker, Factory 是实现了接口,也继承了接口的实现类。JDK动态代理产生的代理类无法强制转换成接口的实现类类型,所以是无法调用接口实现类中自定义的方法。但CGLIB因为继承了接口实现类,所以可以转换成接口实现类类型,并且在接口实现类中自定义的方法也被增强了。