2018-04-03

參考 http://lrd.ele.me/2017/01/09/dynamic_proxy/

jdk 代理

rem target 實例化的對象

--> Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    --> Class<?> cl = getProxyClass0(loader, intfs);  // intfs 對象接口
    重點 :
        --> return proxyClassCache.get(loader, interfaces);  // proxyClassCache 緩存
            -->  Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); // 獲取subkey   [KeyFactory類型] subKeyFactory
                --> Supplier<V> supplier = valuesMap.get(subKey); value 域  <ProxyClassFactory> 類型  supplier.apply() == ProxyClassFactory.apply()
                        --> Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
                            //Verify that the class loader resolves the name of this interface to the same Class object.
                            //Verify that the Class object actually represents an interface.
                            //Verify that this interface is not a duplicate.
                        --> interfaceClass = Class.forName(intf.getName(), false, loader);  // 逐個遍歷 interfaces  
                        --> long num = nextUniqueNumber.getAndIncrement();
                        --> String proxyName = proxyPkg + proxyClassNamePrefix + num; //生成名稱
                        --> byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); // 生成classbyte  [核心]
                        --> return defineClass0(loader, proxyName,  proxyClassFile, 0, proxyClassFile.length); //定義類
                --> factory = new Factory(key, parameter, subKey, valuesMap);// valueFactory 即 valuesMap 中 value 的封裝                    
    --> final Constructor<?> cons = cl.getConstructor(constructorParams);
    --> final InvocationHandler ih = h;
    --> return cons.newInstance(new Object[]{h});


生成$Proxy0 class 反編譯

static {
    try {
        m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
        m2 = Class.forName("java.lang.Object").getMethod("toString");
        m3 = Class.forName("BookFacade").getMethod("addBook");
        m0 = Class.forName("java.lang.Object").getMethod("hashCode");
    } catch (NoSuchMethodException var2) {
        throw new NoSuchMethodError(var2.getMessage());
    } catch (ClassNotFoundException var3) {
        throw new NoClassDefFoundError(var3.getMessage());
    }
}
生成的方法
  public final void addBook() throws  {
    try {
        super.h.invoke(this, m3, (Object[])null);
    } catch (RuntimeException | Error var2) {
        throw var2;
    } catch (Throwable var3) {
        throw new UndeclaredThrowableException(var3);
    }
}

jdk proxy的調(diào)用是一個反射調(diào)用的過程

cglib 動態(tài)代理的實現(xiàn)分析

代理類繼承自org.springframework.cglib.proxy.MethodInterceptor  實現(xiàn)intercept方法
關(guān)鍵代碼 ::     
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(this.target.getClass()); // 將接口直接設(shè)置成BookFacadeProxyCglib 實現(xiàn)類
    // 回調(diào)方法 
    // enhancer.setCallbackType(this.getClass()); 
    enhancer.setCallback(this);     //設(shè)置回調(diào)
    // 創(chuàng)建代理對象
    return enhancer.create();  
    --> return this.createHelper(); 
        -->  this.setNamePrefix(this.superclass.getName());設(shè)置NamePrefix 
        --> return super.create(KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter, this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID));

 // 代理產(chǎn)生的幾個類

    fastclass        --> public class BookFacadeImpl$$EnhancerByCGLIB$$677aba98$$FastClassByCGLIB$$dcb5b9cc extends FastClass 
    class            --> public class BookFacadeImpl$$EnhancerByCGLIB$$677aba98 extends BookFacadeImpl implements Factory 
    keyFactory       --> public class Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$4ce19e8f extends KeyFactory implements EnhancerKey 
    methodwrapperkey --> public class MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$552be97a extends KeyFactory implements MethodWrapperKey  
 
 
 整個aop執(zhí)行過程 
    [ BookFacadeImpl$$EnhancerByCGLIB$$677aba98 ] addbook 
    --> [ MethodIntercepter.intercept ] 
    < before method exe >
    --> [ BookFacadeImpl$$EnhancerByCGLIB$$677aba98$$FastClassByCGLIB$$dcb5b9cc.invoke ]
    --> [ BookFacadeImpl$$EnhancerByCGLIB$$677aba98.CGLIB$addBook$0  >>>> (final 方法) ]
    --> [ super[BookFacadeImpl].addBook ]
    < after method exe >
    --> [ MethodIntercepter.intercept ] 
   
    調(diào)用路徑
    //使用的是這個對象
    --> BookFacadeImpl$$EnhancerByCGLIB$$677aba98 
        |    private boolean CGLIB$BOUND;
        |    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;  //threadlocal 中存放callback
        |    private static final Callback[] CGLIB$STATIC_CALLBACKS;   // static callback
        |    private MethodInterceptor CGLIB$CALLBACK_0;               // 用戶自己實現(xiàn)的MethodInterceptor
        |    private static final Method CGLIB$addBook$0$Method;       // 父類中的callback 方法
        |    private static final MethodProxy CGLIB$addBook$0$Proxy;   // 方法代理 MethodProxy 類
        |    private static final Object[] CGLIB$emptyArgs;            // 方法參數(shù)
        |    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 var0 = Class.forName("BookFacadeImpl$$EnhancerByCGLIB$$677aba98"); //當(dāng)前類的實例
        |        Class var1;
        |        Method[] var10000 = ReflectUtils.findMethods(new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        |        CGLIB$finalize$1$Method = var10000[0];
        |        CGLIB$finalize$1$Proxy = MethodProxy.create(var1, var0, "()V", "finalize", "CGLIB$finalize$1");
        |        CGLIB$equals$2$Method = var10000[1];
        |        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        |        CGLIB$toString$3$Method = var10000[2];
        |        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        |        CGLIB$hashCode$4$Method = var10000[3];
        |        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        |        CGLIB$clone$5$Method = var10000[4];
        |        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
                 // var1 賦值
        |        CGLIB$addBook$0$Method = ReflectUtils.findMethods(new String[]{"addBook", "()V"}, (var1 = Class.forName("BookFacadeImpl")).getDeclaredMethods())[0];
        |        CGLIB$addBook$0$Proxy = MethodProxy.create(var1, var0, "()V", "addBook", "CGLIB$addBook$0");
        |    }
    --> addBook()
        --> 
            -->| public final void addBook() {
            -->|     MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;//獲取當(dāng)前類中的methodintercepter
            -->|     if (this.CGLIB$CALLBACK_0 == null) {
            -->|         CGLIB$BIND_CALLBACKS(this);                //如果為空
            -->|         var10000 = this.CGLIB$CALLBACK_0;
            -->|     }
            -->| 
            -->|     if (var10000 != null) {
                         // 執(zhí)行MethodInterceptor 類中的方法 <實現(xiàn)了MethodInterceptor的類> -->  
            -->|         var10000.intercept(this, CGLIB$addBook$0$Method, CGLIB$emptyArgs, CGLIB$addBook$0$Proxy); 
            -->|     } else {
            -->|         super.addBook();
            -->|     }
            -->| }

            -->| private static final void CGLIB$BIND_CALLBACKS(Object var0) {
            -->|     BookFacadeImpl$$EnhancerByCGLIB$$677aba98 var1 = (BookFacadeImpl$$EnhancerByCGLIB$$677aba98)var0;
            -->|     if (!var1.CGLIB$BOUND) {
            -->|         var1.CGLIB$BOUND = true;
            -->|         Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            -->|         if (var10000 == null) {
            -->|             var10000 = CGLIB$STATIC_CALLBACKS;
            -->|             if (CGLIB$STATIC_CALLBACKS == null) {
            -->|                 return;
            -->|             }
            -->|        }
            -->|        
            -->|         var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
            -->|     }
            -->|     
            -->| }

            實現(xiàn)了 MethodInterceptor的類
            -->|>|public class BookFacadeProxyCglib implements MethodInterceptor {
            -->|>|    private Object target;
            -->|>|
            -->|>|    public Object getInstance(Object target) {
            -->|>|        this.target = target;
            -->|>|        Enhancer enhancer = new Enhancer();
            -->|>|        enhancer.setSuperclass(this.target.getClass());
            -->|>|        // 回調(diào)方法
            -->|>|        // enhancer.setCallbackType(this.getClass());
            -->|>|        enhancer.setCallback(this);
            -->|>|        // 創(chuàng)建代理對象
            -->|>|        return enhancer.create();
            -->|>|    }
            -->|>|    
            -->|>|    @Override
            -->|>|    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            -->|>|        System.out.println("before run!");
                          // 執(zhí)行MethodProxy的invokeSuper
            -->|>|        proxy.invokeSuper(obj, args);
            -->|>|        System.out.println("after run!");
            -->|>|        return null;
            -->|>|    }
            -->|>|}

            MethodProxy的invokeSuper 方法
            -->| public Object invokeSuper(Object obj, Object[] args) throws Throwable {
            -->|     try {
            -->|         this.init();

                        ------> | private void init() {
                        ------> |     if (this.fastClassInfo == null) {
                        ------> |         Object var1 = this.initLock;
                        ------> |         synchronized(this.initLock) {
                        ------> |             if (this.fastClassInfo == null) {
                        ------> |                 MethodProxy.CreateInfo ci = this.createInfo;
                        ----------------------- 對應(yīng)  --> CGLIB$addBook$0$Proxy = MethodProxy.create(var1, var0, "()V", "addBook", "CGLIB$addBook$0");
                        MethodProxy 中的變量賦值
                        [ c1 = var1 = BookFacadeImpl                            ]  
                        [ c2 = var0 = BookFacadeImpl$$EnhancerByCGLIB$$677aba98 ]
                        [ name1 = addBook         = new Signature(name1, desc); ]
                        [ name2 = CGLIB$addBook$0 = new Signature(name2, desc); ]
                                            --> | public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
                                            --> |     MethodProxy proxy = new MethodProxy();
                                            --> |     proxy.sig1 = new Signature(name1, desc);
                                            --> |     proxy.sig2 = new Signature(name2, desc);
                                            --> |     proxy.createInfo = new MethodProxy.CreateInfo(c1, c2);
                                            --> |     return proxy;
                                            --> | }
                        -----------------------
                        ------> |                 MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo(); //實例化FastClassInfo
                        ------> |                 fci.f1 = helper(ci, ci.c1);
                        ----------------------------------------------------------------------------------------------------------------------
                                                    ---->| private static FastClass helper(MethodProxy.CreateInfo ci, Class type) {
                                                    ---->|    Generator g = new Generator();
                                                    ---->|    g.setType(type);
                                                    ---->|    g.setClassLoader(ci.c2.getClassLoader());
                                                    ---->|    g.setNamingPolicy(ci.namingPolicy);
                                                    ---->|    g.setStrategy(ci.strategy);
                                                    ---->|    g.setAttemptLoad(ci.attemptLoad);
                                                    ---->|    return g.create();
                                                             >| org.springframework.cglib.core.AbstractClassGenerator#create //最終調(diào)用AbstractClassGenerator的create方法
                                                    ---->|   }
                        ----------------------------------------------------------------------------------------------------------------------
                        ------> |                 fci.f2 = helper(ci, ci.c2);
                        ------> |                 fci.i1 = fci.f1.getIndex(this.sig1);
                        ------> |                 fci.i2 = fci.f2.getIndex(this.sig2);
                        ------> |                 this.fastClassInfo = fci;
                        ------> |                 this.createInfo = null;
                        ------> |             }
                        ------> |         }
                        ------> |     }
                        ------> | }
            -->|         MethodProxy.FastClassInfo fci = this.fastClassInfo;
            -->|         return fci.f2.invoke(fci.i2, obj, args);
            -->|     } catch (InvocationTargetException var4) {
            -->|         throw var4.getTargetException();
            -->|     }
            -->| }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锐极,一起剝皮案震驚了整個濱河市笙僚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灵再,老刑警劉巖肋层,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亿笤,死亡現(xiàn)場離奇詭異,居然都是意外死亡栋猖,警方通過查閱死者的電腦和手機净薛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掂铐,“玉大人罕拂,你說我怎么就攤上這事∪桑” “怎么了爆班?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辱姨。 經(jīng)常有香客問我柿菩,道長,這世上最難降的妖魔是什么雨涛? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任枢舶,我火速辦了婚禮,結(jié)果婚禮上替久,老公的妹妹穿的比我還像新娘凉泄。我一直安慰自己,他們只是感情好蚯根,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布后众。 她就那樣靜靜地躺著,像睡著了一般颅拦。 火紅的嫁衣襯著肌膚如雪蒂誉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天距帅,我揣著相機與錄音右锨,去河邊找鬼。 笑死碌秸,一個胖子當(dāng)著我的面吹牛绍移,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播讥电,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼登夫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了允趟?” 一聲冷哼從身側(cè)響起恼策,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涣楷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體分唾,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年狮斗,在試婚紗的時候發(fā)現(xiàn)自己被綠了绽乔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡碳褒,死狀恐怖折砸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情沙峻,我是刑警寧澤睦授,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站摔寨,受9級特大地震影響去枷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜是复,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一删顶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淑廊,春花似錦逗余、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜀备,卻和暖如春关摇,著一層夾襖步出監(jiān)牢的瞬間荒叶,已是汗流浹背碾阁。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留些楣,地道東北人脂凶。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像愁茁,于是被迫代替她去往敵國和親蚕钦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容