转载自:https://www.jianshu.com/p/20203286ccd9

先通过demo演示效果,然后进行源码分析
demo用Enhancer结合MethodInterceptor以及CallBackFilter完成

这里Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展

1.demo

拦截器1

package cglib;import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;public class CglibProxy implements MethodInterceptor {//实现MethodInterceptor接口,定义方法的拦截器@Overridepublic Object intercept(Object o, Method method, Object[] objects,MethodProxy methodProxy) throws Throwable {System.out.println("pre");//通过代理类调用父类中的方法,即实体类方法Object result = methodProxy.invokeSuper(o, objects);System.out.println("after");return result;}
}

拦截器2

package cglib;import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;public class CglibProxy2 implements MethodInterceptor {//实现MethodInterceptor接口,定义方法的拦截器@Overridepublic Object intercept(Object o, Method method, Object[] objects,MethodProxy methodProxy) throws Throwable {System.out.println("pre1");//通过代理类调用父类中的方法,即实体类方法Object result = methodProxy.invokeSuper(o, objects);System.out.println("after1");return result;}
}

回调过滤器CallbackFilter

package cglib;import net.sf.cglib.proxy.CallbackFilter;
import java.lang.reflect.Method;public class filter implements CallbackFilter {@Overridepublic int accept(Method method) {if(method.getName().equals("toString")) {return 1;}return 0;}
}

测试类

package cglib;import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;public class CglibLearn {//定义委托类,可以不是接口static class serviceImpl {void say(){System.out.println("say");}}public static Object getProxyInstance(Object realSubject) {Enhancer enhancer = new Enhancer();//需要创建子类的类,即定义委托类enhancer.setSuperclass(realSubject.getClass());//设置两个CallBack以及CallbackFilterCallback[] callbacks=new Callback[2];callbacks[0]=new CglibProxy();callbacks[1]=new CglibProxy2();enhancer.setCallbacks(callbacks);enhancer.setCallbackFilter(new filter());//通过字节码技术动态创建子类实例return enhancer.create();}public static void main(String[] args) {//将sam,class文件写到硬盘System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, ".//");//通过生成子类的方式创建代理类serviceImpl impl = (serviceImpl)getProxyInstance(new serviceImpl());impl.say();impl.toString();}
}

输出,自己想想就知道

2.源码分析

看源码之前,最好先了解下callBack和callBackFilter是有什么作用,再看会带着问题看

直接进测试类的enhancer.create();探究这个代理对象是怎么生成的,下面按照几个注意的环节来讲,会经历整个创建过程

2.1根据代理类的配置作为组合Key

net.sf.cglib.proxy.Enhancer#create()
net.sf.cglib.proxy.Enhancer#createHelper()private Object createHelper() {//进行有效性验证,比如有多个callBack却没有callBackFiltervalidate();if (superclass != null) {setNamePrefix(superclass.getName());} else if (interfaces != null) {setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());}//先根据KEY_FACTORY 以当前代理类的配置信息 生成一个组合Key,再利用这个组合Key,进行createreturn super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,ReflectUtils.getNames(interfaces),filter,callbackTypes,useFactory,interceptDuringConstruction,serialVersionUID));}

这里注意
KEY_FACTORY 就是前两节讲到的根据KeyFactory,完成multi-value的一个Key
可以理解成这里如果代理类的配置,作为Key,一样的换就能利用缓存了,后面会讲到利用的缓存

private static final EnhancerKey KEY_FACTORY =(EnhancerKey)KeyFactory.create(EnhancerKey.class);public interface EnhancerKey {public Object newInstance(String type,String[] interfaces,CallbackFilter filter,Type[] callbackTypes,boolean useFactory,boolean interceptDuringConstruction,Long serialVersionUID);}

2.2 利用缓存完成根据Key获取Class信息,进而生成代理对象

这一块代码比较简单,和之前jdk动态代理利用的缓存差不多,在KeyFactory那一节也讲过,还是列出来就行,看注释就够了

protected Object create(Object key) {try {//需要缓存的类Class gen = null;synchronized (source) {ClassLoader loader = getClassLoader();Map cache2 = null;//根据来源区分,根据classLoader进行一级缓存cache2 = (Map)source.cache.get(loader);if (cache2 == null) {cache2 = new HashMap();cache2.put(NAME_KEY, new HashSet());source.cache.put(loader, cache2);} else if (useCache) {//用缓存Reference ref = (Reference)cache2.get(key);gen = (Class) (( ref == null ) ? null : ref.get()); }if (gen == null) {Object save = CURRENT.get();CURRENT.set(this);try {this.key = key;if (attemptLoad) {try {gen = loader.loadClass(getClassName());} catch (ClassNotFoundException e) {// ignore}}if (gen == null) {//结合生成策略,得到类的字节码byte[] b = strategy.generate(this);String className = ClassNameReader.getClassName(new ClassReader(b));getClassNameCache(loader).add(className);//根据字节码生成类gen = ReflectUtils.defineClass(className, b, loader);}if (useCache) {//根据传入的key,进行二级缓存cache2.put(key, new WeakReference(gen));}//根据类,生成实例return firstInstance(gen);} finally {CURRENT.set(save);}}}return firstInstance(gen);} catch (RuntimeException e) {throw e;} catch (Error e) {throw e;} catch (Exception e) {throw new CodeGenerationException(e);}}

可以看出来,关注点集中在代理类的生成,即

byte[] b = strategy.generate(this);

2.3.代理类的生成

继续跟进

net.sf.cglib.core.GeneratorStrategy#generate
net.sf.cglib.core.DefaultGeneratorStrategy#generate
net.sf.cglib.core.ClassGenerator#generateClass
net.sf.cglib.proxy.Enhancer#generateClass

最终就是利用Enhancer来生成代理类,下面有详细的注释

public void generateClass(ClassVisitor v) throws Exception {Class sc = (superclass == null) ? Object.class : superclass;if (TypeUtils.isFinal(sc.getModifiers()))throw new IllegalArgumentException("Cannot subclass final class " + sc);List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));filterConstructors(sc, constructors);// Order is very important: must add superclass, then// its superclass chain, then each interface and// its superinterfaces.List actualMethods = new ArrayList();List interfaceMethods = new ArrayList();final Set forcePublic = new HashSet();/*根据规定的父类,生成需要的方法,参见 CglibLearn$serviceImpl$$EnhancerByCGLIB$$81852b18.classactualMethods记录所有经过过滤的方法interfaceMethods和forcePublic的size都为0*/getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);for(int i=0;i<actualMethods.size();i++) {System.out.println("actualMethods is " + actualMethods.get(i));}/*把actualMethods中,非abstract,非native,非synchronized方法的修饰符全部变成final将转化后的方法信息MethodInfo列表 记录在methods中*/List methods = CollectionUtils.transform(actualMethods, new Transformer() {public Object transform(Object value) {Method method = (Method)value;int modifiers = Constants.ACC_FINAL| (method.getModifiers()& ~Constants.ACC_ABSTRACT& ~Constants.ACC_NATIVE& ~Constants.ACC_SYNCHRONIZED);if (forcePublic.contains(MethodWrapper.create(method))) {modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;}return ReflectUtils.getMethodInfo(method, modifiers);}});ClassEmitter e = new ClassEmitter(v);//开始生成代理类 继承指定的superClasse.begin_class(Constants.V1_2,Constants.ACC_PUBLIC,getClassName(),Type.getType(sc),(useFactory ?TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :TypeUtils.getTypes(interfaces)),Constants.SOURCE_FILE);//将构造函数信息 记录在 constructorInfo 中List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);if (!interceptDuringConstruction) {e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);}e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);if (serialVersionUID != null) {e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);}//声明field,是定义的callbackType,设置了几个callBack,这里就有几个field,名字为CGLIB$CALLBACK_xxx(为id)for (int i = 0; i < callbackTypes.length; i++) {e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);}//根据methods,actualMethods生成方法,完成callBack,callBackFilter的处理emitMethods(e, methods, actualMethods);//生成构造函数emitConstructors(e, constructorInfo);//这几个暂时不清楚emitSetThreadCallbacks(e);emitSetStaticCallbacks(e);emitBindCallbacks(e);if (useFactory) {int[] keys = getCallbackKeys();emitNewInstanceCallbacks(e);emitNewInstanceCallback(e);emitNewInstanceMultiarg(e, constructorInfo);emitGetCallback(e, keys);emitSetCallback(e, keys);emitGetCallbacks(e);emitSetCallbacks(e);}e.end_class();}

备注,上面利用asm完成类的生成,主要步骤如下

1.getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
这个方法就是递归的将superClass的父类,父接口的函数全部记录在method中,
然后过滤掉原有类的static方法,private方法,和superClass位于不同包的类中的方法(不知道何时会出现这种情况???),以及final方法

获取,并且过滤完之后,剩下的方法是

void cglib.CglibLearn$serviceImpl.say()
protected void java.lang.Object.finalize() throws java.lang.Throwable
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException

2.emitMethods
这个函数是用来生成代理类里面的methods,非常重要,列出源码如下

/*methods 是方法的信息列表, 每一个类型都是MethodInfoactualMethods 是真实的方法, 每一个类型都是Method*/private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) {/*根据callbackTypes得到对应的generator,跟进去看比如callbackType是MethodInterceptor.class,对应的generator就是MethodInterceptorGenerator.INSTANCE*/CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes);Map groups = new HashMap();final Map indexes = new HashMap();final Map originalModifiers = new HashMap();final Map positions = CollectionUtils.getIndexMap(methods);final Map declToBridge = new HashMap();Iterator it1 = methods.iterator();Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null;while (it1.hasNext()) {MethodInfo method = (MethodInfo)it1.next();Method actualMethod = (it2 != null) ? (Method)it2.next() : null;/*根据定义的callBackFilter的accept值,判断由哪一个callBack来过滤当前方法filter这里默认是net.sf.cglib.proxy.Enhancer.ALL_ZERO,即accept永远返回0*/int index = filter.accept(actualMethod);if (index >= callbackTypes.length) {throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index);}originalModifiers.put(method, new Integer((actualMethod != null) ? actualMethod.getModifiers() : method.getModifiers()));//通过indexes这个map记录每个map该由第几个callBack来处理indexes.put(method, new Integer(index));//让这个callBack对应的generator 记录下来它要处理这个methodList group = (List)groups.get(generators[index]);if (group == null) {groups.put(generators[index], group = new ArrayList(methods.size()));}group.add(method);// Optimization: build up a map of Class -> bridge methods in class// so that we can look up all the bridge methods in one pass for a class.if (TypeUtils.isBridge(actualMethod.getModifiers())) {Set bridges = (Set)declToBridge.get(actualMethod.getDeclaringClass());if (bridges == null) {bridges = new HashSet();declToBridge.put(actualMethod.getDeclaringClass(), bridges);}bridges.add(method.getSignature());             }}final Map bridgeToTarget = new BridgeMethodResolver(declToBridge).resolveAll();Set seenGen = new HashSet();CodeEmitter se = ce.getStaticHook();se.new_instance(THREAD_LOCAL);se.dup();se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL);se.putfield(THREAD_CALLBACKS_FIELD);final Object[] state = new Object[1];//下面context定义了如何根据callBack信息,来进行代码生成CallbackGenerator.Context context = new CallbackGenerator.Context() {public ClassLoader getClassLoader() {return Enhancer.this.getClassLoader();}public int getOriginalModifiers(MethodInfo method) {return ((Integer)originalModifiers.get(method)).intValue();}//根据method判断对应的callBack下标public int getIndex(MethodInfo method) {return ((Integer)indexes.get(method)).intValue();}/*根据下标让当前method生成“调用对应callBack”的代码这也表现出来一个method只有一个callBack*/public void emitCallback(CodeEmitter e, int index) {emitCurrentCallback(e, index);}public Signature getImplSignature(MethodInfo method) {return rename(method.getSignature(), ((Integer)positions.get(method)).intValue());}public void emitInvoke(CodeEmitter e, MethodInfo method) {// If this is a bridge and we know the target was called from invokespecial,// then we need to invoke_virtual w/ the bridge target instead of doing// a super, because super may itself be using super, which would bypass// any proxies on the target.Signature bridgeTarget = (Signature)bridgeToTarget.get(method.getSignature());if (bridgeTarget != null) {// TODO: this assumes that the target has wider or the same type// parameters than the current.  // In reality this should always be true because otherwise we wouldn't// have had a bridge doing an invokespecial.// If it isn't true, we would need to checkcast each argument// against the target's argument typese.invoke_virtual_this(bridgeTarget);Type retType = method.getSignature().getReturnType();                    // Not necessary to cast if the target & bridge have// the same return type. // (This conveniently includes void and primitive types,// which would fail if casted.  It's not possible to // covariant from boxed to unbox (or vice versa), so no having// to box/unbox for bridges).// TODO: It also isn't necessary to checkcast if the return is// assignable from the target.  (This would happen if a subclass// used covariant returns to narrow the return type within a bridge// method.)if (!retType.equals(bridgeTarget.getReturnType())) {e.checkcast(retType);}} else {e.super_invoke(method.getSignature());}}public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) {CodeEmitter e = EmitUtils.begin_method(ce, method);if (!interceptDuringConstruction &&!TypeUtils.isAbstract(method.getModifiers())) {Label constructed = e.make_label();e.load_this();e.getfield(CONSTRUCTED_FIELD);e.if_jump(e.NE, constructed);e.load_this();e.load_args();e.super_invoke();e.return_value();e.mark(constructed);}return e;}};for (int i = 0; i < callbackTypes.length; i++) {CallbackGenerator gen = generators[i];if (!seenGen.contains(gen)) {seenGen.add(gen);/*每个callBack对应的generator要处理的列表为fmethods下面将每个method对应的callBack调用关系,生成代码*/final List fmethods = (List)groups.get(gen);if (fmethods != null) {try {gen.generate(ce, context, fmethods);gen.generateStatic(se, context, fmethods);} catch (RuntimeException x) {throw x;} catch (Exception x) {throw new CodeGenerationException(x);}}}}se.return_value();se.end_method();}

这里的主要工作如下

int index = filter.accept(actualMethod); 这里是判断当前method是由哪一个callBack来处理...
定义如何根据callBack信息,来进行代码生成
CallbackGenerator.Context context = new CallbackGenerator.Context(){xxx}
...每个callBack对应的generator要处理的列表为fmethods
下面将每个method对应的callBack调用关系,生成代码
final List fmethods = (List)groups.get(gen);

2.4.代理类的结果

本地生成了文件

image.png

其中,CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b文件的细节在intellij并没有显示完全,用
http://www.javadecompilers.com/result 去decompile一下,可以看到细节,一定要展示出来,方便理解代理类创建的过程

/** Decompiled with CFR 0_118.* * Could not load the following classes:*  cglib.CglibLearn*  cglib.CglibLearn$serviceImpl*  net.sf.cglib.core.ReflectUtils*  net.sf.cglib.core.Signature*  net.sf.cglib.proxy.Callback*  net.sf.cglib.proxy.Factory*  net.sf.cglib.proxy.MethodInterceptor*  net.sf.cglib.proxy.MethodProxy*/
package cglib;import cglib.CglibLearn;
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;public class CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b
extends CglibLearn.serviceImpl
implements Factory {private boolean CGLIB$BOUND;private static final ThreadLocal CGLIB$THREAD_CALLBACKS;private static final Callback[] CGLIB$STATIC_CALLBACKS;private MethodInterceptor CGLIB$CALLBACK_0;private MethodInterceptor CGLIB$CALLBACK_1;private static final Method CGLIB$say$0$Method;private static final MethodProxy CGLIB$say$0$Proxy;private static final Object[] CGLIB$emptyArgs;private static final Method CGLIB$finalize$1$Method;private static final MethodProxy CGLIB$finalize$1$Proxy;private static final Method CGLIB$equals$2$Method;private static final MethodProxy CGLIB$equals$2$Proxy;private static final Method CGLIB$toString$3$Method;private static final MethodProxy CGLIB$toString$3$Proxy;private static final Method CGLIB$hashCode$4$Method;private static final MethodProxy CGLIB$hashCode$4$Proxy;private static final Method CGLIB$clone$5$Method;private static final MethodProxy CGLIB$clone$5$Proxy;static void CGLIB$STATICHOOK1() {CGLIB$THREAD_CALLBACKS = new ThreadLocal();CGLIB$emptyArgs = new Object[0];Class class_ = Class.forName("cglib.CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b");Class class_2 = Class.forName("java.lang.Object");Method[] arrmethod = ReflectUtils.findMethods((String[])new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (Method[])class_2.getDeclaredMethods());CGLIB$finalize$1$Method = arrmethod[0];CGLIB$finalize$1$Proxy = MethodProxy.create(class_2, class_, (String)"()V", (String)"finalize", (String)"CGLIB$finalize$1");CGLIB$equals$2$Method = arrmethod[1];CGLIB$equals$2$Proxy = MethodProxy.create(class_2, class_, (String)"(Ljava/lang/Object;)Z", (String)"equals", (String)"CGLIB$equals$2");CGLIB$toString$3$Method = arrmethod[2];CGLIB$toString$3$Proxy = MethodProxy.create(class_2, class_, (String)"()Ljava/lang/String;", (String)"toString", (String)"CGLIB$toString$3");CGLIB$hashCode$4$Method = arrmethod[3];CGLIB$hashCode$4$Proxy = MethodProxy.create(class_2, class_, (String)"()I", (String)"hashCode", (String)"CGLIB$hashCode$4");CGLIB$clone$5$Method = arrmethod[4];CGLIB$clone$5$Proxy = MethodProxy.create(class_2, class_, (String)"()Ljava/lang/Object;", (String)"clone", (String)"CGLIB$clone$5");class_2 = Class.forName("cglib.CglibLearn$serviceImpl");CGLIB$say$0$Method = ReflectUtils.findMethods((String[])new String[]{"say", "()V"}, (Method[])class_2.getDeclaredMethods())[0];CGLIB$say$0$Proxy = MethodProxy.create(class_2, class_, (String)"()V", (String)"say", (String)"CGLIB$say$0");}final void CGLIB$say$0() {super.say();}final void say() {MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;if (methodInterceptor == null) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);methodInterceptor = this.CGLIB$CALLBACK_0;}if (methodInterceptor != null) {Object object = methodInterceptor.intercept((Object)this, CGLIB$say$0$Method, CGLIB$emptyArgs, CGLIB$say$0$Proxy);return;}super.say();}final void CGLIB$finalize$1() throws Throwable {super.finalize();}protected final void finalize() throws Throwable {MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;if (methodInterceptor == null) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);methodInterceptor = this.CGLIB$CALLBACK_0;}if (methodInterceptor != null) {Object object = methodInterceptor.intercept((Object)this, CGLIB$finalize$1$Method, CGLIB$emptyArgs, CGLIB$finalize$1$Proxy);return;}super.finalize();}final boolean CGLIB$equals$2(Object object) {return super.equals(object);}public final boolean equals(Object object) {MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;if (methodInterceptor == null) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);methodInterceptor = this.CGLIB$CALLBACK_0;}if (methodInterceptor != null) {Object object2 = methodInterceptor.intercept((Object)this, CGLIB$equals$2$Method, new Object[]{object}, CGLIB$equals$2$Proxy);return object2 == null ? false : (Boolean)object2;}return super.equals(object);}final String CGLIB$toString$3() {return super.toString();}public final String toString() {MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_1;if (methodInterceptor == null) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);methodInterceptor = this.CGLIB$CALLBACK_1;}if (methodInterceptor != null) {return (String)methodInterceptor.intercept((Object)this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy);}return super.toString();}final int CGLIB$hashCode$4() {return super.hashCode();}public final int hashCode() {MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;if (methodInterceptor == null) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);methodInterceptor = this.CGLIB$CALLBACK_0;}if (methodInterceptor != null) {Object object = methodInterceptor.intercept((Object)this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);return object == null ? 0 : ((Number)object).intValue();}return super.hashCode();}final Object CGLIB$clone$5() throws CloneNotSupportedException {return super.clone();}protected final Object clone() throws CloneNotSupportedException {MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;if (methodInterceptor == null) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);methodInterceptor = this.CGLIB$CALLBACK_0;}if (methodInterceptor != null) {return methodInterceptor.intercept((Object)this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy);}return super.clone();}public static MethodProxy CGLIB$findMethodProxy(Signature signature) {String string = signature.toString();switch (string.hashCode()) {case -1574182249: {if (!string.equals("finalize()V")) break;return CGLIB$finalize$1$Proxy;}case -909388886: {if (!string.equals("say()V")) break;return CGLIB$say$0$Proxy;}case -508378822: {if (!string.equals("clone()Ljava/lang/Object;")) break;return CGLIB$clone$5$Proxy;}case 1826985398: {if (!string.equals("equals(Ljava/lang/Object;)Z")) break;return CGLIB$equals$2$Proxy;}case 1913648695: {if (!string.equals("toString()Ljava/lang/String;")) break;return CGLIB$toString$3$Proxy;}case 1984935277: {if (!string.equals("hashCode()I")) break;return CGLIB$hashCode$4$Proxy;}}return null;}public CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b() {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b = this;CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b);}public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] arrcallback) {CGLIB$THREAD_CALLBACKS.set(arrcallback);}public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] arrcallback) {CGLIB$STATIC_CALLBACKS = arrcallback;}private static final void CGLIB$BIND_CALLBACKS(Object object) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b = (CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b)((Object)object);if (!cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BOUND) {cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BOUND = true;Object t = CGLIB$THREAD_CALLBACKS.get();if (t != null || (v312 = CGLIB$STATIC_CALLBACKS) != null) {Callback[] arrcallback = (Callback[])t;CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b2 = cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b;cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b2.CGLIB$CALLBACK_1 = (MethodInterceptor)arrcallback[1];cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b2.CGLIB$CALLBACK_0 = (MethodInterceptor)arrcallback[0];}}}public Object newInstance(Callback[] arrcallback) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$SET_THREAD_CALLBACKS(arrcallback);CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$SET_THREAD_CALLBACKS(null);return new CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b();}public Object newInstance(Callback callback) {throw new IllegalStateException("More than one callback object required");}/** Unable to fully structure code* Enabled aggressive block sorting* Lifted jumps to return sites*/public Object newInstance(Class[] var1_1, Object[] var2_2, Callback[] var3_3) {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$SET_THREAD_CALLBACKS(var3_3);switch (var1_1.length) {case 0: {** break;}}throw new IllegalArgumentException("Constructor not found");
lbl6: // 1 sources:CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$SET_THREAD_CALLBACKS(null);return new CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b();}public Callback getCallback(int n) {MethodInterceptor methodInterceptor;CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b = this;switch (n) {case 0: {methodInterceptor = cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$CALLBACK_0;break;}case 1: {methodInterceptor = cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$CALLBACK_1;break;}default: {methodInterceptor = null;}}return methodInterceptor;}public void setCallback(int n, Callback callback) {switch (n) {case 0: {this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback;break;}case 1: {this.CGLIB$CALLBACK_1 = (MethodInterceptor)callback;break;}}}public Callback[] getCallbacks() {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$BIND_CALLBACKS((Object)this);CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b = this;return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1};}public void setCallbacks(Callback[] arrcallback) {Callback[] arrcallback2 = arrcallback;this.CGLIB$CALLBACK_0 = (MethodInterceptor)arrcallback2[0];Callback[] arrcallback3 = arrcallback2;CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b cglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b = this;this.CGLIB$CALLBACK_1 = (MethodInterceptor)arrcallback2[1];}static {CglibLearn$serviceImpl$$EnhancerByCGLIB$$4e65f4b.CGLIB$STATICHOOK1();}
}

3.测试类的结果分析

自己的demo中
cglib.CglibProxy#intercept和cglib.CglibProxy2#intercept是如何工作的,即调用
impl.say();的时候
拦截器是如何拦截的

参照上面得到的decompile文件

final void say() {MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;if (methodInterceptor == null) {CGLIB$BIND_CALLBACKS(this);methodInterceptor = this.CGLIB$CALLBACK_0;}if (methodInterceptor != null) {methodInterceptor.intercept(this, CGLIB$say$0$Method, CGLIB$emptyArgs, CGLIB$say$0$Proxy);} else {say();}}

很容易看出来了,
另外比较一下

image.png

这里就是CGLIB$CALLBACK_1了,这个是怎么办到的?

其实在之前讲net.sf.cglib.proxy.Enhancer#emitMethods时候就说了

net.sf.cglib.proxy.CallbackGenerator.Context#getIndex
配合net.sf.cglib.proxy.MethodInterceptorGenerator#generate里面

context.emitCallback(e, context.getIndex(method));

完成了每个method知道自己对应的callBack是第几个

另外,拦截器拦截时,

Object result = methodProxy.invokeSuper(o, objects);

invokeSuper是干吗的
这在下一节FastClass会讲

4.思考

4.1 CallbackFilter 和 CallBack有什么关系

一个method只能有一个CallBack(不定义也会有默认的)
CallBackFilter就是完成一个mapping的过程,比如
a,b method 用 A callBack
c,d method 用 B callBack
源码里也有体现出来一个method对应一个callBack

4.2 method与callBack之间的对应的关系是如何实现的

net.sf.cglib.proxy.Enhancer#emitMethods中
每个method通过 int index = filter.accept(actualMethod); 知道当前method由第几个callBack处理
然后由net.sf.cglib.proxy.MethodInterceptorGenerator#generate

context.emitCallback(e, context.getIndex(method));

将这种对应关系写到类中去

4.3 Enhancer如何根据callBack,callBackFilter完成代理类class文件的定义

net.sf.cglib.proxy.Enhancer#generateClass
主要是
net.sf.cglib.proxy.Enhancer#getMethods(java.lang.Class, java.lang.Class[], java.util.List, java.util.List, java.util.Set)
net.sf.cglib.proxy.Enhancer#emitMethods

4.4 与jdk动态代理区别

这里cglib底层是用的asm,而jdk动态代理没有

4.5 Enhancer的"enhance"体现在哪

个人理解,可能并不准确
1.完成callBack以及callBackFilter等的aop处理
2.完成代理类say()的调用 转发给 方法代理即CGLIB$say$0$Proxy

methodInterceptor.intercept(this, CGLIB$say$0$Method, CGLIB$emptyArgs, CGLIB$say$0$Proxy);
//其中
CGLIB$say$0$Proxy = MethodProxy.create(cls2, cls, "()V", "say", "CGLIB$say$0");

最终将cls2的say方法转发给cls的CGLIB$say$0方法(并不是上文列出来的CGLIB$say$0),这个和fastClass相关,下一节再讲。

4.6 CGLIB$STATICHOOK1()作用

创建各种方法代理即MethodProxy,在下一节和fastClass一起讲

5.备注

net.sf.cglib.proxy.Enhancer#generateClass还有一些emit其他细节,目前没有涉及到,没有看

6.问题

findMethodProxy作用是啥,没有看到调用

7.refer

http://javadox.com/cglib/cglib/2.2/net/sf/cglib/proxy/Enhancer.html#generateClass(org.objectweb.asm.ClassVisitor)
http://cglib.sourceforge.net/apidocs/
http://www.cnblogs.com/cruze/p/3865180.html

作者:赤子心_d709
链接:https://www.jianshu.com/p/20203286ccd9
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

cglib demo以及Enhancer源码解析相关推荐

  1. CGLIB 动态代理用例及源码解析

    CGLIB 动态代理 参考链接:https://blog.csdn.net/yhl_jxy/article/details/80633194 参考链接:https://www.jianshu.com/ ...

  2. Java SPI 源码解析及 demo 讲解

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:Java实现QQ登录和微博登录个人原创+1博客:点击前往,查看更多 作者:JlDang 来源:https://s ...

  3. spring aop 注入源码解析

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

  4. spring aop 注入源码解析 1

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

  5. HandlerThread和IntentService源码解析

    简介 首先我们先来了解HandlerThread和IntentService是什么,以及为什么要将这两者放在一起分析. HandlerThread: HandlerThread 其实是Handler ...

  6. dataset__getitem___PyTorch源码解析与实践(1):数据加载Dataset,Sampler与DataLoader

    献给学习PyTorch在路上或者计划较深入理解PyTorch的同行者们 写在前面 笔者一直使用tf,大势所趋决定转PyTorch,这个系列就作为我学习PyTorch的笔记与心得. 网络上PyTorch ...

  7. Handler消息机制(九):IntentService源码解析

    作者:jtsky 链接:https://www.jianshu.com/p/0a150ec09a32 简介 首先我们先来了解HandlerThread和IntentService是什么,以及为什么要将 ...

  8. iOS开发之Masonry框架源码解析

    Masonry是iOS在控件布局中经常使用的一个轻量级框架,Masonry让NSLayoutConstraint使用起来更为简洁.Masonry简化了NSLayoutConstraint的使用方式,让 ...

  9. JDK源码解析 Comparator 中的策略模式

    JDK源码解析 Comparator 中的策略模式.在Arrays类中有一个 sort() 方法,如下: public class Arrays{public static <T> voi ...

最新文章

  1. Django celery6.4
  2. php10-e 豪华版,华为畅享 10e 规格参数
  3. Java基础学习总结(9)——this关键字
  4. leetcode算法题--最长等差数列★
  5. 机器学习和图像资源整理
  6. <DependencyManagement>记录
  7. std::string格式化输入输出
  8. oracle关闭 manager,Oracle Enterprise Manager 11g 启停
  9. python控制条件语句_Python条件控制语句
  10. Centos7 安装mysql 需要自己下载 rpm
  11. 机器学习工程师 - Udacity 强化学习 Part Nine
  12. 1159 最大全0子矩阵
  13. PMP考试今年改革吗?
  14. 螺纹的规定,http://www.doc88.com/p-30089302852.html
  15. BIOS学习之Beyong Bios
  16. PowerVR 6系列架构分析
  17. python笔记更新(网络编程)
  18. 谷歌浏览器怎么关闭硬件加速?
  19. 【2022感恩节活动营销理念】跨境电商卖家必知 !
  20. JS自写带描述标签云

热门文章

  1. 减震透气的清爽跑鞋,让跑步更轻松,咕咚10K悦弹体验
  2. C语言对于char*和char[]的理解
  3. python download
  4. Android进阶学习-自定义主题(3)
  5. springboot项目:老年教育学习系统fte91(java+VUE+Mybatis+Maven+Mysql)
  6. 【make】make常见问题
  7. 7家顶级机构投资策略分析
  8. tomcat启动过程-start启动
  9. PSTN与VoIP相关知识
  10. 大数据培训有前途吗,大数据工资一般多少?