• Dubbo-SPI原理


    参考:https://mp.weixin.qq.com

    官网地址:https://dubbo.apache.org/zh/docs/v2.7/dev/source/dubbo-spi/

    双亲委托模式的弊端

      判断类是否加载的时候,应用类加载器会顺着双亲路径往上判断,直到启动类加载器.但是启动类加载器不会往下询问,这个委托路线是单向的,即顶层的类加载器,无法访问底层的类加载器所加载的类
      启动类加载器中的类为系统的核心类,比如,在系统类中,提供了一个接口,并且该接口还提供了一个工厂方法用于创建该接口的实例,但是该接口的实现类在应用层中,接口和工厂方法在启动类加载器中,就会出现工厂方法无法创建由应用类加载器加载的应用实例问题.

      拥有这样问题的组件有很多,比如JDBC(DataSource、Driver)、Xml parser等.JDBC本身是java连接数据库的一个标准,是进行数据库连接的抽象层,由java编写的一组类和接口组成,接口的实现由各个数据库厂商来完成

     文件内容com.mysql.cj.jdbc.Driver

    双亲委托模式的补充 

      在Java中,把核心类(rt.jar)中提供外部服务,可由应用层自行实现的接口,这种方式成为spi

    ExtensionLoader

      org.apache.dubbo.common.extension.ExtensionLoader#getExtension源码分析

    public T getExtension(String name) {
    	// 默认包装成Wrapper对象
    	return getExtension(name, true);
    }
    
    public T getExtension(String name, boolean wrap) {
    	if (StringUtils.isEmpty(name)) {
    		throw new IllegalArgumentException("Extension name == null");
    	}
    	// 返回默认的扩展实现类
    	if ("true".equals(name)) {
    		return getDefaultExtension();
    	}
    	// volatile + synchronized + double-check 获取或创建扩展点实现类
    	final Holder<Object> holder = getOrCreateHolder(name);
    	Object instance = holder.get();
    	if (instance == null) {
    		synchronized (holder) {
    			instance = holder.get();
    			if (instance == null) {
    				instance = createExtension(name, wrap);
    				holder.set(instance);
    			}
    		}
    	}
    	return (T) instance;
    }
    

      createExtension源码分析 

    private T createExtension(String name, boolean wrap) {
    	// 从配置文件中加载所有的拓展类,可得到“配置项名称”到“配置类”的映射关系表
    	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);
    		}
    		// 向实例中注入依赖,为变量赋值
    		injectExtension(instance);
    
    		if (wrap) {
    			List<Class<?>> wrapperClassesList = new ArrayList<>();
    			if (cachedWrapperClasses != null) {
    				wrapperClassesList.addAll(cachedWrapperClasses);
                       // 根据Activate注解中的order属性值排序  wrapperClassesList.sort(WrapperComparator.COMPARATOR); Collections.reverse(wrapperClassesList); } // 循环创建 Wrapper 实例 if (CollectionUtils.isNotEmpty(wrapperClassesList)) { for (Class<?> wrapperClass : wrapperClassesList) { Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class); if (wrapper == null || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) { // 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例 // 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } } } // 是否实现了 Lifecycle,生命周期的初始化处理 initExtension(instance); return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } }

      getExtensionClasses源码分析

    private Map<String, Class<?>> getExtensionClasses() {
    	// 从缓存中获取已加载的拓展类
    	Map<String, Class<?>> classes = cachedClasses.get();
    	if (classes == null) {
    		synchronized (cachedClasses) {
    			classes = cachedClasses.get();
    			if (classes == null) {
    				// 加载所有的扩展类
    				classes = loadExtensionClasses();
    				cachedClasses.set(classes);
    			}
    		}
    	}
    	return classes;
    }
    

      loadExtensionClasses源码分析

    private Map<String, Class<?>> loadExtensionClasses() {
    	// 对 SPI 注解进行解析,如果存在默认扩展名则获取并缓存
    	cacheDefaultExtensionName();
    
    	Map<String, Class<?>> extensionClasses = new HashMap<>();
    
    	// 根据加载策略加载指定文件夹下的配置文件
    	for (LoadingStrategy strategy : strategies) {
    		loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
    		loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
    	}
    
    	return extensionClasses;
    }
    
    private void cacheDefaultExtensionName() {
    	// 获取 SPI 注解,这里的 type 变量是在调用 getExtensionLoader 方法时传入的
    	final SPI defaultAnnotation = type.getAnnotation(SPI.class);
    	if (defaultAnnotation == null) {
    		return;
    	}
    
    	String value = defaultAnnotation.value();
    	if ((value = value.trim()).length() > 0) {
    		// 对 SPI 注解内容进行切分
    		String[] names = NAME_SEPARATOR.split(value);
    		// 检测 SPI 注解内容是否合法,不合法则抛出异常
    		if (names.length > 1) {
    			throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
    					+ ": " + Arrays.toString(names));
    		}
    		// 设置默认名称,参考 getDefaultExtension 方法
    		if (names.length == 1) {
    			cachedDefaultName = names[0];
    		}
    	}
    }
    

      loadDirectory源码分析  

    private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
                                   boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
    	// fileName = 文件夹路径 + type 全限定名
    	String fileName = dir + type;
    	try {
    		Enumeration<java.net.URL> urls = null;
    		ClassLoader classLoader = findClassLoader();
    
    		// try to load from ExtensionLoader's ClassLoader first
    		if (extensionLoaderClassLoaderFirst) {
    			ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
    			if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
    				urls = extensionLoaderClassLoader.getResources(fileName);
    			}
    		}
    
    		// 根据文件名加载所有的同名文件
    		if (urls == null || !urls.hasMoreElements()) {
    			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, overridden, excludedPackages);
    			}
    		}
    	} catch (Throwable t) {
    		logger.error("Exception occurred when loading extension class (interface: " +
    				type + ", description file: " + fileName + ").", t);
    	}
    }
    

      loadResource源码分析

    private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
    						  java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
    	try {
    		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 && !isExcluded(line, excludedPackages)) {
    							// 加载类,并通过 loadClass 方法对类进行缓存
    							loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden);
    						}
    					} 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);
    	}
    }
    

      loadClass源码分析

    private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,
    					   boolean overridden) throws NoSuchMethodException {
    	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)) {
    		// 设置 cachedAdaptiveClass缓存
    		cacheAdaptiveClass(clazz, overridden);
    	}
    	// 检测 clazz 是否是 Wrapper 类型,判断依据是是否有当前 type 的有参构造器
    	else if (isWrapperClass(clazz)) {
    		// 存储 clazz 到 cachedWrapperClasses 缓存中
    		cacheWrapperClass(clazz);
    	}
    	// 程序进入此分支,表明 clazz 是一个普通的拓展类
    	else {
    		// 检测 clazz 是否有默认的构造方法,如果没有,则抛出异常
    		clazz.getConstructor();
    		if (StringUtils.isEmpty(name)) {
    			// 如果 name 为空,则尝试从 Extension 注解中获取 name,或使用小写的类名作为 name
    			name = findAnnotationName(clazz);
    			if (name.length() == 0) {
    				throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
    			}
    		}
    
    		// 切分 name
    		String[] names = NAME_SEPARATOR.split(name);
    		if (ArrayUtils.isNotEmpty(names)) {
    			// 如果类上有 Activate 注解,则使用 names 数组的第一个元素作为键,
    			// 存储 name 到 Activate 注解对象的映射关系
    			cacheActivateClass(clazz, names[0]);
    			for (String n : names) {
    				// 存储 Class 到名称的映射关系
    				cacheName(clazz, n);
    				// 存储名称到 Class 的映射关系
    				saveInExtensionClass(extensionClasses, clazz, n, overridden);
    			}
    		}
    	}
    }
    

    IOC

      通过 setter 方法注入依赖,createExtension方法中执行完getExtensionClasses方法,从配置文件中加载完所有的拓展类后,获得了目标扩展实例,进行依赖注入

      injectExtension源码分析

    private T injectExtension(T instance) {
    
    	if (objectFactory == null) {
    		return instance;
    	}
    
    	try {
    		// 遍历目标类的所有方法
    		for (Method method : instance.getClass().getMethods()) {
    			// 检测方法是否以 set 开头,且方法仅有一个参数,且方法访问级别为 public
    			if (!isSetter(method)) {
    				continue;
    			}
    			/**
    			 * Check {@link DisableInject} to see if we need auto injection for this property
    			 */
    			if (method.getAnnotation(DisableInject.class) != null) {
    				continue;
    			}
    			// 获取 setter 方法参数类型
    			Class<?> pt = method.getParameterTypes()[0];
    			if (ReflectUtils.isPrimitives(pt)) {
    				continue;
    			}
    
    			try {
    				// 获取属性名,比如 setName 方法对应属性名 name
    				String property = getSetterProperty(method);
    				// 从 ObjectFactory 中获取依赖对象,SPI方式,Spring方式
    				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;
    } 

    AOP 

      createExtension方法中

    if (wrap) {
    
    	List<Class<?>> wrapperClassesList = new ArrayList<>();
    	if (cachedWrapperClasses != null) {
    		wrapperClassesList.addAll(cachedWrapperClasses);
    		// 根据Activate注解中的order属性值排序
    		wrapperClassesList.sort(WrapperComparator.COMPARATOR);
    		Collections.reverse(wrapperClassesList);
    	}
    
    	// 循环创建 Wrapper 实例
    	if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
    		for (Class<?> wrapperClass : wrapperClassesList) {
    			Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
    			// Wrapper注解为空,或者不为空但是符合匹配条件
    			if (wrapper == null
    					|| (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
    				// 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例,实现了AOP
    				// 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量
    				instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
    			}
    		}
    	}
    }
    

    Adaptive

      getAdaptiveExtension源码分析 

    public T getAdaptiveExtension() {
    	Object instance = cachedAdaptiveInstance.get();
    	if (instance == null) {
    		// 并发情况下,如果有error直接报错,不去竞争锁了
    		if (createAdaptiveInstanceError != null) {
    			throw new IllegalStateException("Failed to create adaptive instance: " +
    					createAdaptiveInstanceError.toString(),
    					createAdaptiveInstanceError);
    		}
    
    		synchronized (cachedAdaptiveInstance) {
    			instance = cachedAdaptiveInstance.get();
    			if (instance == null) {
    				try {
    					// 创建Adaptive实例
    					instance = createAdaptiveExtension();
    					cachedAdaptiveInstance.set(instance);
    				} catch (Throwable t) {
    					createAdaptiveInstanceError = t;
    					throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
    				}
    			}
    		}
    	}
    
    	return (T) instance;
    }
    
    private T createAdaptiveExtension() {
    	try {
    		// 获取Adaptive扩展类字节码,反射获取实例
    		return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    	} catch (Exception e) {
    		throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
    	}
    }
    
    private Class<?> getAdaptiveExtensionClass() {
    	getExtensionClasses();
    	if (cachedAdaptiveClass != null) {
    		return cachedAdaptiveClass;
    	}
    	// Javassist方式或JDK方式创建Adaptive扩展类字节码
    	return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }
    

      createAdaptiveExtensionClass源码分析

    private Class<?> createAdaptiveExtensionClass() {
    	// 创建Adaptive类java代码
    	String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
    	ClassLoader classLoader = findClassLoader();
    	org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
    	// 编译Adaptive类java代码,创建Adaptive类字节码获取Adaptive类Class对象
    	return compiler.compile(code, classLoader);
    }
    

      AdaptiveClassCodeGenerator#generate源码分析

    public String generate() {
    	// no need to generate adaptive class since there's no adaptive method found.
    	if (!hasAdaptiveMethod()) {
    		throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!");
    	}
    
    	StringBuilder code = new StringBuilder();
    	// package信息
    	code.append(generatePackageInfo());
    	// import信息
    	code.append(generateImports());
    	// 类声明信息 public class %s$Adaptive implements %s
    	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();
    }
    

      java代码结果示例

    package org.apache.dubbo.common.extension.adaptive;
    import org.apache.dubbo.common.extension.ExtensionLoader;
    public class HasAdaptiveExt$Adaptive implements org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt {
    public java.lang.String echo(org.apache.dubbo.common.URL arg0, java.lang.String arg1)  {
    if (arg0 == null) throw new IllegalArgumentException("url == null");
    org.apache.dubbo.common.URL url = arg0;
    String extName = url.getParameter("has.adaptive.ext", "adaptive");
    if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt) name from url (" + url.toString() + ") use keys([has.adaptive.ext])");
    org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt extension = (org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt)ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt.class).getExtension(extName);
    return extension.echo(arg0, arg1);
    }
    }
    

    Compiler  

      利用Javassist、JDK将java代码编译为Class对象 

      

  • 相关阅读:
    Rest
    docker-4
    Arrays.asList
    docker-3
    docker
    docker
    linux-ss
    jackson
    Java将图片的路径转为Base64,VUE前端显示
    java base64视频存到本地或服务器
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/14699756.html
Copyright © 2020-2023  润新知