摘要:的類繼承關(guān)系在實現(xiàn)中,默認使用進行動態(tài)編譯,不使用。那么這個是一個裝飾類還是一個動態(tài)代理類從上面的接口的定義并不能看出,跟進方法來看所以是一個裝飾類。
前面分析SPI機制時,提到createAdaptiveExtensionClass()自動生成和編譯一個動態(tài)的adpative類。
Compiler的類繼承關(guān)系:
在Dubbo實現(xiàn)中,默認使用JavassistCompiler進行動態(tài)編譯,不使用JdKComplier。這一點從Compiler接口的實現(xiàn)中可以看出。
@SPI("javassist") public interface Compiler { /** * Compile java source code. * * @param code Java source code * @param classLoader TODO * @return Compiled class */ Class> compile(String code, ClassLoader classLoader); }
可以看到,這里使用了@SPI注解,指定了使用javassist。
回顧前面的調(diào)用流程:
-->createAdaptiveExtensionClass() -->createAdaptiveExtensionClassCode() -->com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); -->compiler.compile(code, classLoader) -->AdaptiveCompiler.compile(code, classLoader) -->AbstractCompiler.compile(code, classLoader) -->Class> doCompile(String name, String source) -->JavassistCompiler.doCompile(String name, String source) -->cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain());//編譯成class返回
根據(jù)前面分析SPI機制時得出的結(jié)論:
getExtensionLoader(Classtype) 就是為該接口new 一個ExtensionLoader,然后緩存起來。 getAdaptiveExtension() 獲取一個擴展類,如果@Adaptive注解在類上就是一個裝飾類;如果注解在方法上就是一個動態(tài)代理類,例如Protocol$Adaptive對象。 getExtension(String name) 獲取一個指定對象。
這里首先為Compiler接口創(chuàng)建了一個ExtensionLoader。然后調(diào)用getAdaptiveExtension()獲取擴展類。那么這個Compiler是一個裝飾類還是一個動態(tài)代理類?從上面的Compiler接口的定義并不能看出,跟進compile()方法來看:
@Adaptive public class AdaptiveCompiler implements Compiler
所以Compiler是一個裝飾類。
接著看createAdaptiveExtensionClass()具體實現(xiàn):
private Class> createAdaptiveExtensionClass() { String code = createAdaptiveExtensionClassCode(); ClassLoader classLoader = findClassLoader(); com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); return compiler.compile(code, classLoader); }
這里會執(zhí)行到AdaptiveCompiler的實現(xiàn):
@Adaptive public class AdaptiveCompiler implements Compiler { private static volatile String DEFAULT_COMPILER; public static void setDefaultCompiler(String compiler) { DEFAULT_COMPILER = compiler; } public Class> compile(String code, ClassLoader classLoader) { Compiler compiler; ExtensionLoaderloader = ExtensionLoader.getExtensionLoader(Compiler.class); String name = DEFAULT_COMPILER; // copy reference if (name != null && name.length() > 0) { compiler = loader.getExtension(name); } else { compiler = loader.getDefaultExtension(); } return compiler.compile(code, classLoader); } }
這里DEFAULT_COMPILER執(zhí)行compile時并未賦值,所以會執(zhí)行else分支,這里最終會根據(jù)@SPI("javassist")獲取JavassistCompiler。然后使用其compile()進行編譯code,這里會調(diào)用到抽象類AbstractCompiler的實現(xiàn):
public abstract class AbstractCompiler implements Compiler { private static final Pattern PACKAGE_PATTERN = Pattern.compile("packages+([$_a-zA-Z][$_a-zA-Z0-9.]*);"); private static final Pattern CLASS_PATTERN = Pattern.compile("classs+([$_a-zA-Z][$_a-zA-Z0-9]*)s+"); public Class> compile(String code, ClassLoader classLoader) { code = code.trim(); Matcher matcher = PACKAGE_PATTERN.matcher(code); String pkg; if (matcher.find()) { pkg = matcher.group(1); } else { pkg = ""; } matcher = CLASS_PATTERN.matcher(code); String cls; if (matcher.find()) { cls = matcher.group(1); } else { throw new IllegalArgumentException("No such class name in " + code); } String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls; try { return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass())); } catch (ClassNotFoundException e) { if (!code.endsWith("}")) { throw new IllegalStateException("The java code not endsWith "}", code: " + code + " "); } try { return doCompile(className, code); } catch (RuntimeException t) { throw t; } catch (Throwable t) { throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code: " + code + " , stack: " + ClassUtils.toString(t)); } } } protected abstract Class> doCompile(String name, String source) throws Throwable; }
在上述代碼中首先會去使用類加載器Class.forName去加載目標類,如果類本身(如動態(tài)代理類$Adaptive)不存在則會走到異常處理代碼,doCompile()這里會調(diào)用到JavassistCompiler的具體實現(xiàn)。在該類中最后會返回編譯的class:
cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain());
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/68531.html
摘要:如前所說,的目的是獲取一個指定實現(xiàn)類的對象。接下來從子模塊下的包的開始分析先來看這里繼承自類。如沒有擴展點,在擴展點實現(xiàn)調(diào)用該方法,并返回結(jié)果。前面已經(jīng)分析過,就是使用讀取文件并緩存的反轉(zhuǎn)控制,就是從和里面提取對象賦值。 如前所說,Dubbo SPI的目的是獲取一個指定實現(xiàn)類的對象。那么Dubbo是通過什么方式獲取的呢?其實是調(diào)用ExtensionLoader.getExtension...
摘要:二注解該注解為了保證在內(nèi)部調(diào)用具體實現(xiàn)的時候不是硬編碼來指定引用哪個實現(xiàn),也就是為了適配一個接口的多種實現(xiàn),這樣做符合模塊接口設計的可插拔原則,也增加了整個框架的靈活性,該注解也實現(xiàn)了擴展點自動裝配的特性。 Dubbo擴展機制SPI 前一篇文章《dubbo源碼解析(一)Hello,Dubbo》是對dubbo整個項目大體的介紹,而從這篇文章開始,我將會從源碼來解讀dubbo再各個模塊的實...
摘要:第二種是,是一款字節(jié)碼引擎工具,能夠在運行時編譯生成。后記該部分相關(guān)的源碼解析地址該文章講解了遠程調(diào)用中關(guān)于代理的部分,關(guān)鍵部分在于基于實現(xiàn)的字節(jié)碼技術(shù)來支撐動態(tài)代理。 遠程調(diào)用——Proxy 目標:介紹遠程調(diào)用代理的設計和實現(xiàn),介紹dubbo-rpc-api中的各種proxy包的源碼。 前言 首先聲明叫做代理,代理在很多領(lǐng)域都存在,最形象的就是現(xiàn)在朋友圈的微商代理,廠家委托代理幫他們...
摘要:編譯完成后在目錄下有的包二部署首先將編譯后的包放到目錄,啟動。自動解壓包如圖是的一個應用服務器。也依賴填寫你的服務的部署地址。最后重啟,重啟之前保證服務處于運行狀態(tài)。 一.dubbo編譯1、先從github上下載dubbo源碼,地址:https://github.com/alibaba/du... showImg(https://segmentfault.com/img/bV1fir?...
閱讀 2159·2021-11-22 15:22
閱讀 1299·2021-11-11 16:54
閱讀 1830·2021-09-23 11:32
閱讀 3021·2021-09-22 10:02
閱讀 1781·2019-08-30 12:59
閱讀 1095·2019-08-29 16:27
閱讀 631·2019-08-29 13:21
閱讀 2470·2019-08-28 17:57