Source analysis:
/ ** * Get the extension class * / @SuppressWarnings ( "an unchecked" ) public T GetExtension (String name) { IF (StringUtils.isEmpty (name)) { the throw new new an IllegalArgumentException ( "the Extension name == null" ); } // Gets the default implementation class expansion IF ( "to true" .equals (name)) { return getDefaultExtension (); } // holder for holding a target object Final holder <Object> = holder getOrCreateHolder (name); Object instance = holder. GET (); //Double check IF (instance == null ) { the synchronized (holder) { instance = holder.get (); IF (instance == null ) { // create expanding instance instance = createExtension (name); // set the instance to the holder holder.set (instance); } } } return (T) instance; }
// 创建拓展对象 @SuppressWarnings("unchecked") private T createExtension(String name) { Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { // 通过反射创建实例 EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance =(T) EXTENSION_INSTANCES.get (clazz); } // injected into the instance dependent injectExtension (instance); the Set <Class <>> wrapperClasses =? CachedWrapperClasses; IF (CollectionUtils.isNotEmpty (wrapperClasses)) { // cycle created instance Wrapper for (Class <?> wrapperClass: wrapperClasses) { // the current instance as a parameter to the constructor Wrapper, and creates Wrapper instance by reflection. // then injected into Wrapper dependency example last instance reassigned to the Wrapper instance variable instance = injectExtension ((T) wrapperClass.getConstructor (type) .newInstance (instance)); } } return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } }
// loaded from the configuration file expand all classes available "configuration item name" to "configuration classes" mapping table Private the Map <String, Class <? >> getExtensionClasses () { // get from the cache is loaded the expansion of the class the Map <String, class <= >> classes? cachedClasses.get (); // double check IF (classes == null ) { the synchronized (cachedClasses) { classes = cachedClasses.get (); IF (classes == null ) { // load class expand classes = loadExtensionClasses (); cachedClasses.set (classes); } } } return classes; }
// synchronized in getExtensionClasses private Map<String, Class<?>> loadExtensionClasses() { cacheDefaultExtensionName(); Map<String, Class<?>> extensionClasses = new HashMap<>(); // 加载指定文件夹下的配置文件 loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName()); 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 loadDirectory (the Map <String, Class <>>? extensionClasses, dir String, String of the type) { // fileName = folder path + type the fully qualified name String fileName = dir + of the type; the try { Enumeration <java.net.URL > URLs; ClassLoader classLoader = findClassLoader (); // load all the file name of the same file IF (classLoader =! null ) { URLs = ClassLoader.getResources (fileName); } the 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); } }