SPI原始碼的閱讀我們從 ServiceConfig.java 開始。
ExtensionLoader.javaprivate ExtensionLoader(Class<?> type) { this.type = type; // 用於建立當前type型別擴充套件類例項的 objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());} //判斷類上是否有SPI註解private static <T> boolean withExtensionAnnotation(Class<T> type) { return type.isAnnotationPresent(SPI.class);}@SuppressWarnings("unchecked")public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { if (type == null) { throw new IllegalArgumentException("Extension type == null"); } if (!type.isInterface()) { throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); } if (!withExtensionAnnotation(type)) { // 對SPI註解的判斷 throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { //如果Map中存在該key,則直接返回該key的value。如果Map中沒有該key,那麼就新增該key並返回null EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); // 建立一個loader例項 loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader;}
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
我們這裡傳入的型別是 Protocol.class 型別,所以這裡不是null。準備跟蹤 getExtensionLoader()
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { if (type == null) { throw new IllegalArgumentException("Extension type == null"); } if (!type.isInterface()) { throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); } if (!withExtensionAnnotation(type)) { // 對SPI註解的判斷 throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { //如果Map中存在該key,則直接返回該key的value。如果Map中沒有該key,那麼就新增該key並返回null EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); // 建立一個ExtensionFactory型別的loader例項 loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader;}
回到ExtensionLoader(Class type)構造方法中跟蹤getAdaptiveExtension()public T getAdaptiveExtension() { // 從快取中獲取相應例項 Object instance = cachedAdaptiveInstance.get(); // DCL,雙重檢測鎖 if (instance == null) { if (createAdaptiveInstanceError == null) { synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 建立當前SPI的自適應例項 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } else { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } } return (T) instance;}private T createAdaptiveExtension() { try { // getAdaptiveExtensionClass() 獲取adaptive類,是個class // newInstance() 呼叫adaptive類的無參構造器建立一個adpative例項 // injectExtension() 呼叫例項的setter,完成相關屬性例項的注入 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); }}private Class<?> getAdaptiveExtensionClass() { // 用於將當前SPI介面的所有擴充套件類class快取起來(四類:普通擴充套件類、adaptive類、wrapper類,及activate類) getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } // 根據@Adaptive方法,建立adaptive類 return cachedAdaptiveClass = createAdaptiveExtensionClass(); }private Map<String, Class<?>> getExtensionClasses() { // cachedClasses 集合中快取著當前SPI介面的所有直接擴充套件類(普通擴充套件類與activate類) Map<String, Class<?>> classes = cachedClasses.get(); if (classes == null) { synchronized (cachedClasses) { classes = cachedClasses.get(); if (classes == null) { // 載入四類擴充套件類 classes = loadExtensionClasses(); cachedClasses.set(classes); } } } // 返回當前SPI介面的所有直接擴充套件類 return classes; } private Map<String, Class<?>> loadExtensionClasses() { // 快取SPI介面的預設副檔名 cacheDefaultExtensionName(); // 定義一個map,用於存放直接擴充套件類 Map<String, Class<?>> extensionClasses = new HashMap<>(); loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName()); // 相容2.6版本 loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName()); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); return extensionClasses; }private void cacheDefaultExtensionName() { // 獲取當前SPI介面的SPI註解 final SPI defaultAnnotation = type.getAnnotation(SPI.class); if (defaultAnnotation != null) { // 獲取SPI註解的value屬性值,即預設副檔名 String value = defaultAnnotation.value(); if ((value = value.trim()).length() > 0) { // 使用逗號分隔value屬性值 String[] names = NAME_SEPARATOR.split(value); if (names.length > 1) { throw new IllegalStateException("More than 1 default extension name on extension " + type.getName() + ": " + Arrays.toString(names)); } if (names.length == 1) { cachedDefaultName = names[0]; } } }} private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) { // 拼接出配置檔名 // 例:META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory String fileName = dir + type; try { Enumeration<java.net.URL> urls; ClassLoader classLoader = findClassLoader(); // 為什麼一個檔名會加載出來多個url? // 因為一個檔名在整個dubbo框架中會存在多個同名檔案,每個檔案會加載出來一個url if (classLoader != null) { urls = classLoader.getResources(fileName); } else { urls = ClassLoader.getSystemResources(fileName); } if (urls != null) { while (urls.hasMoreElements()) { java.net.URL resourceURL = urls.nextElement(); loadResource(extensionClasses, classLoader, resourceURL); // 載入資源 } } } catch (Throwable t) { logger.error("Exception occurred when loading extension class (interface: " + type + ", description file: " + fileName + ").", t); } }private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) { try { // try-with-resource,帶資源的try語句,是JDK7的特性 try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { final int ci = line.indexOf('#'); if (ci >= 0) { line = line.substring(0, ci); } line = line.trim(); if (line.length() > 0) { try { String name = null; int i = line.indexOf('='); if (i > 0) { name = line.substring(0, i).trim(); // 副檔名 line = line.substring(i + 1).trim(); // 擴充套件類名 } if (line.length() > 0) { // 將指定的類載入並快取 loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name); } } catch (Throwable t) { IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t); exceptions.put(line, e); } } } } } catch (Throwable t) { logger.error("Exception occurred when loading extension class (interface: " + type + ", class file: " + resourceURL + ") in " + resourceURL, t); } } private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException { // 判斷當前類是否實現當前的SPI介面了 if (!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Error occurred when loading extension class (interface: " + type + ", class line: " + clazz.getName() + "), class " + clazz.getName() + " is not subtype of interface."); } // 判斷當前類是否是adaptive類 if (clazz.isAnnotationPresent(Adaptive.class)) { // 快取這個類 cacheAdaptiveClass(clazz); } else if (isWrapperClass(clazz)) { // 判斷當前類是否是wrapper類 // 快取這個類 cacheWrapperClass(clazz); } else { // 處理普通擴充套件類與activate類的情況 // 驗證擴充套件類是否具有無參構造器。 // 若沒有,則直接丟擲異常,後面的程式碼就不會執行了。若有,則什麼也不做 clazz.getConstructor(); // 處理擴充套件類為空的情況 if (StringUtils.isEmpty(name)) { // 找一個副檔名 name = findAnnotationName(clazz); if (name.length() == 0) { throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL); } } // 使用逗號分隔副檔名 String[] names = NAME_SEPARATOR.split(name); if (ArrayUtils.isNotEmpty(names)) { // 使用第一個副檔名快取activate類 cacheActivateClass(clazz, names[0]); for (String n : names) { // 快取第一個name cacheName(clazz, n); // 將當前class快取到一個map saveInExtensionClass(extensionClasses, clazz, n); } } } }private void cacheAdaptiveClass(Class<?> clazz) { if (cachedAdaptiveClass == null) { cachedAdaptiveClass = clazz; // 若快取中已經存在了adaptive類,且與當前類不同,則丟擲異常。因為adaptive類只能有一個 } else if (!cachedAdaptiveClass.equals(clazz)) { throw new IllegalStateException("More than 1 adaptive class found: " + cachedAdaptiveClass.getClass().getName() + ", " + clazz.getClass().getName()); }}private void cacheWrapperClass(Class<?> clazz) { if (cachedWrapperClasses == null) { cachedWrapperClasses = new ConcurrentHashSet<>(); } // 將這個類寫入到快取set cachedWrapperClasses.add(clazz);}private void cacheName(Class<?> clazz, String name) { // 使用這個class快取第一個name if (!cachedNames.containsKey(clazz)) { cachedNames.put(clazz, name); }}private void saveInExtensionClass(Map<String, Class<?>> extensionClasses, Class<?> clazz, String name) { Class<?> c = extensionClasses.get(name); if (c == null) { // 每一個副檔名都會與class配對寫入到map中 extensionClasses.put(name, clazz); } else if (c != clazz) { throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName()); }}
快取類的原始碼閱讀完了,接下來返回到 private Class<?> getAdaptiveExtensionClass() 中 createAdaptiveExtensionClass() 的adaptive類建立的過程
private Class<?> createAdaptiveExtensionClass() { // 生成adaptive類程式碼 String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate(); ClassLoader classLoader = findClassLoader(); // 獲取到Compiler型別的adaptive類例項 org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader .getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class) .getAdaptiveExtension(); // 呼叫adaptiveCompiler的compile() return compiler.compile(code, classLoader);}
AdaptiveClassCodeGenerator.javapublic String generate() { // no need to generate adaptive class since there's no adaptive method found. // 若當前SPI介面中不包含@Adaptive方法,則丟擲異常 if (!hasAdaptiveMethod()) { throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!"); } // 透過字串拼接方式,生成程式碼 StringBuilder code = new StringBuilder(); code.append(generatePackageInfo()); //生成包資訊程式碼 code.append(generateImports()); //生成需要匯入的包路徑程式碼 code.append(generateClassDeclaration());//生成類名稱和頭部資訊 Method[] methods = type.getMethods(); for (Method method : methods) { code.append(generateMethod(method)); //生生該類中的方法 } code.append("}"); if (logger.isDebugEnabled()) { logger.debug(code.toString()); } return code.toString();}
返回到 ExtensionLoader.java 跟蹤 createAdaptiveExtensionClass() 中的 compile() 動態編譯方法
private static volatile String DEFAULT_COMPILER; public static void setDefaultCompiler(String compiler) { DEFAULT_COMPILER = compiler; } @Override public Class<?> compile(String code, ClassLoader classLoader) { Compiler compiler; ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class); String name = DEFAULT_COMPILER; // copy reference if (name != null && name.length() > 0) { compiler = loader.getExtension(name); } else { // 獲取預設副檔名的例項,即javassistCompiler的例項 compiler = loader.getDefaultExtension(); } // 呼叫javassistCompiler的compile() return compiler.compile(code, classLoader); }}
ExtensionLoader.java// 獲取指定名稱的擴充套件類例項public T getExtension(String name) { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } if ("true".equals(name)) { return getDefaultExtension(); } // 從我們剛才跟蹤過的這個熟系的快取裡面根據指定名稱 來獲取例項 final Holder<Object> holder = getOrCreateHolder(name); Object instance = holder.get(); if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { // 建立指定名稱的擴充套件類例項 instance = createExtension(name); holder.set(instance); } } } return (T) instance;}private T createExtension(String name) { // getExtensionClasses() 返回當前SPI介面的所有直接擴充套件類,是個map // 其key為副檔名,value為直接擴充套件類的class Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { // 從快取中獲取指定類對應的例項,若為null,則建立一個例項 T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } // 呼叫instance例項的setter完成注入 injectExtension(instance); // 獲取當前SPI介面型別的所有wrapper類 Set<Class<?>> wrapperClasses = cachedWrapperClasses; // 遍歷所有wrapper,逐層對instance例項進行包裝 if (CollectionUtils.isNotEmpty(wrapperClasses)) { for (Class<?> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } // 返回的是包裝過的instance return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } } private T createExtension(String name) { // getExtensionClasses() 返回當前SPI介面的所有直接擴充套件類,是個map // 其key為副檔名,value為直接擴充套件類的class Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { // 從快取中獲取指定類對應的例項,若為null,則建立一個例項 T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } // 呼叫instance例項的setter完成注入 injectExtension(instance); // 獲取當前SPI介面型別的所有wrapper類 Set<Class<?>> wrapperClasses = cachedWrapperClasses; // 遍歷所有wrapper,逐層對instance例項進行包裝 if (CollectionUtils.isNotEmpty(wrapperClasses)) { for (Class<?> wrapperClass : wrapperClasses) { //看 這裡就是我們之前說的構造方法中傳入了SPI介面的有參建構函式作為注入 // 對該SPI介面進行例項化,用於呼叫SPI介面中的方法時進行方法增強 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } // 返回的是包裝過的instance return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } } private T injectExtension(T instance) { try { if (objectFactory != null) { // 遍歷當前instance中的所有方法 for (Method method : instance.getClass().getMethods()) { // 僅對setter方法進行處理 if (isSetter(method)) { /** * Check {@link DisableInject} to see if we need auto injection for this property */ // 若一個setter方法上有@DisableInject註解,則不進行注入 if (method.getAnnotation(DisableInject.class) != null) { continue; } // 獲取當前setter方法的引數型別 Class<?> pt = method.getParameterTypes()[0]; // 若setter方法的引數型別為基本資料型別,則不進行注入 if (ReflectUtils.isPrimitives(pt)) { continue; } try { // 獲取setter方法的形參名稱 String property = getSetterProperty(method); // 獲取要注入的例項,即setter的實參 Object object = objectFactory.getExtension(pt, property); if (object != null) { // 呼叫setter完成注入 method.invoke(instance, object); } } catch (Exception e) { logger.error("Failed to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(), e); } } } } } catch (Exception e) { logger.error(e.getMessage(), e); } return instance; }複製程式碼
回到 AdaptiveCompiler.java 中的 compile() 方法中來跟蹤一下 javassistCompiler 的實現
AbstractCompiler.java/** * * @param code 生成好的程式碼字串 * @param classLoader 載入code的類載入器 * @return */@Overridepublic Class<?> compile(String code, ClassLoader classLoader) { code = code.trim(); // 從code中將package資訊摘出 Matcher matcher = PACKAGE_PATTERN.matcher(code); String pkg; if (matcher.find()) { pkg = matcher.group(1); } else { pkg = ""; } // 從code中將class資訊摘出 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 { // 載入名稱為className的類 return Class.forName(className, true, org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass())); } catch (ClassNotFoundException e) { if (!code.endsWith("}")) { throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n"); } try { // 呼叫JavassistCompiler的doCompile(),對code使用javassist技術進行動態編譯 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: \n" + code + "\n, stack: " + ClassUtils.toString(t)); } }}
JavassistCompiler.java/** * JavassistCompiler. (SPI, Singleton, ThreadSafe) */public class JavassistCompiler extends AbstractCompiler { private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\s+([\\w\\.\\*]+);\n"); private static final Pattern EXTENDS_PATTERN = Pattern.compile("\\s+extends\\s+([\\w\\.]+)[^\\{]*\\{\n"); private static final Pattern IMPLEMENTS_PATTERN = Pattern.compile("\\s+implements\\s+([\\w\\.]+)\\s*\\{\n"); private static final Pattern METHODS_PATTERN = Pattern.compile("\n(private|public|protected)\\s+"); private static final Pattern FIELD_PATTERN = Pattern.compile("[^\n]+=[^\n]+;"); @Override public Class<?> doCompile(String name, String source) throws Throwable { // 建立一個Builder CtClassBuilder builder = new CtClassBuilder(); // 下面的程式碼都是對builder例項的各種初始化 builder.setClassName(name); // process imported classes Matcher matcher = IMPORT_PATTERN.matcher(source); while (matcher.find()) { builder.addImports(matcher.group(1).trim()); } // process extended super class matcher = EXTENDS_PATTERN.matcher(source); if (matcher.find()) { builder.setSuperClassName(matcher.group(1).trim()); } // process implemented interfaces matcher = IMPLEMENTS_PATTERN.matcher(source); if (matcher.find()) { String[] ifaces = matcher.group(1).trim().split("\\,"); Arrays.stream(ifaces).forEach(i -> builder.addInterface(i.trim())); } // process constructors, fields, methods String body = source.substring(source.indexOf('{') + 1, source.length() - 1); String[] methods = METHODS_PATTERN.split(body); String className = ClassUtils.getSimpleClassName(name); Arrays.stream(methods).map(String::trim).filter(m -> !m.isEmpty()).forEach(method -> { if (method.startsWith(className)) { builder.addConstructor("public " + method); } else if (FIELD_PATTERN.matcher(method).matches()) { builder.addField("private " + method); } else { builder.addMethod("public " + method); } }); // compile ClassLoader classLoader = org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass()); // 使用builder構建出一個CtClass CtClass cls = builder.build(classLoader); // 使用CtClass獲取到一個class return cls.toClass(classLoader, JavassistCompiler.class.getProtectionDomain()); }}
接下來跟蹤一下JDK的動態編譯原始碼
public Class<?> doCompile(String name, String sourceCode) throws Throwable { int i = name.lastIndexOf('.'); String packageName = i < 0 ? "" : name.substring(0, i); String className = i < 0 ? name : name.substring(i + 1); // 字串程式碼會被包裝成一個檔案物件 JavaFileObjectImpl javaFileObject = new JavaFileObjectImpl(className, sourceCode); // javaFileManager介面。主要管理檔案的讀取和輸出位置。 // 因為實現類ForwardingDavaFileManager構造器是protect型別 所以Dubbo擴充套件了自己的 JavaFileManagerImpl javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName, className + ClassUtils.JAVA_EXTENSION, javaFileObject); //生成具體的物件類 Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options, null, Arrays.asList(javaFileObject)).call(); if (result == null || !result) { throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector); } // 使用自定義的 ClassLoaderImpl 完成資源的載入 return classLoader.loadClass(name);}
來源:https://www.tuicool.com/articles/EJZRRrA
最新評論