首頁>技術>

SPI原始碼的閱讀我們從 ServiceConfig.java 開始。

ExtensionLoader.java
private 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.java
public 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

25
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 框架VS架構,兩者異同