8、cglib demo以及Enhancer源碼解析

先通過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接口,定義方法的攔截器
    @Override
    public 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接口,定義方法的攔截器
    @Override
    public 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 {
    @Override
    public 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以及CallbackFilter
        Callback[] 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卻沒有callBackFilter
        validate();
        if (superclass != null) {
            setNamePrefix(superclass.getName());
        } else if (interfaces != null) {
            setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
        }
        //先根據KEY_FACTORY 以當前代理類的配置信息 生成一個組合Key,再利用這個組合Key,進行create
        return 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.class
        actualMethods記錄所有經過過濾的方法
        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);
        //開始生成代理類 繼承指定的superClass
        e.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 是方法的信息列表, 每一個類型都是MethodInfo
        actualMethods 是真實的方法, 每一個類型都是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 記錄下來它要處理這個method
            List 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 types
                    e.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



轉摘於:https://www.jianshu.com/p/20203286ccd9

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章