## JDK 的 SPI 思想 SPI,即 Service Provider Interface。在面向对象的设计里面,模块之间推荐基于接口编程,而不是对实现类进行硬编码,这样做也是为了模块设计的可插拔原则。 比较典型的应用,如 JDBC,Java 定义了一套 JDBC 的接口,但是 Java 本身并不提供对 JDBC 的实现类,而是开发者根据项目实际使用的数据库来选择驱动程序 jar 包,比如 mysql,你就将 mysql-jdbc-connector.jar 引入进来;oracle,你就将 oracle-jdbc-connector.jar 引入进来。在系统跑的时候,碰到你使用 jdbc 的接口,他会在底层使用你引入的那个 jar 中提供的实现类。 ## Dubbo 的 SPI 扩展机制原理 dubbo 自己实现了一套 SPI 机制,并对 JDK 的 SPI 进行了改进。 1. JDK 标准的 SPI 只能通过遍历来查找扩展点和实例化,有可能导致一次性加载所有的扩展点,如果不是所有的扩展点都被用到,就会导致资源的浪费。dubbo 每个扩展点都有多种实现,例如:com.alibaba.dubbo.rpc.Protocol 接口有 InjvmProtocol、DubboProtocol、RmiProtocol、HttpProtocol、HessianProtocol 等实现,如果只是用到其中一个实现,可是加载了全部的实现,会导致资源的浪费。 2. 对配置文件中扩展实现的格式的修改,例如,META-INF/dubbo/com.xxx.Protocol 里的 com.foo.XxxProtocol 格式 改为了 xxx = com.foo.XxxProtocol 这种以键值对的形式,这样做的目的是为了让我们更容易的定位到问题。比如,由于第三方库不存在,无法初始化,导致无法加载扩展点(“A”),当用户配置使用 A 时,dubbo 就会报无法加载扩展点的错误,而不是报哪些扩展点的实现加载失败以及错误原因,**这是因为原来的配置格式没有记录扩展名的 id,导致 dubbo 无法抛出较为精准的异常,这会加大排查问题的难度**。所以改成 key-value 的形式来进行配置。 3. dubbo 的 SPI 机制增加了对 IOC、AOP 的支持,一个扩展点可以直接通过 setter 注入到其他扩展点。 下面我们看一下 Dubbo 的 SPI 扩展机制实现的结构目录。 ![avatar](../../../images/Dubbo/SPI组件目录结构.png) ### SPI 注解 首先看一下 SPI 注解。在某个接口上加上 @SPI 注解后,表明该接口为可扩展接口。比如,协议扩展接口 Protocol,如果使用者在 <dubbo:protocol />、<dubbo:service />、<dubbo:reference /> 都没有指定 protocol 属性 的话,那么就默认使用 DubboProtocol 作为接口 Protocol 的实现,因为在 Protocol 上有 @SPI("dubbo")注解。而这个 protocol 属性值 或者默认值会被当作该接口的实现类中的一个 key,dubbo 会去 META-INF.dubbo.internal 下的 com.alibaba.dubbo.rpc.Protocol 文件中找该 key 对应的 value,源码如下。 ```java /** * 协议接口 * Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。 */ @SPI("dubbo") public interface Protocol { /** * Get default port when user doesn't config the port. */ int getDefaultPort(); /** * 暴露远程服务: * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();
* 2. export() 必须是幂等的,也就是暴露同一个 URL 的 Invoker 两次,和暴露一次没有区别。
* 3. export() 传入的 Invoker 由框架实现并传入,协议不需要关心。
* * @param 服务的类型 * @param invoker 服务的执行体 * @return exporter 暴露服务的引用,用于取消暴露 * @throws RpcException 当暴露服务出错时抛出,比如端口已占用 */ @Adaptive Exporter export(Invoker invoker) throws RpcException; /** * 引用远程服务:
* 1. 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。
* 2. refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求。
* 3. 当 url 中有设置 check=false 时,连接失败不能抛出异常,并内部自动恢复。
* * @param 服务的类型 * @param type 服务的类型 * @param url 远程服务的URL地址 * @return invoker 服务的本地代理 * @throws RpcException 当连接服务提供方失败时抛出 */ @Adaptive Invoker refer(Class type, URL url) throws RpcException; /** * 释放协议:
* 1. 取消该协议所有已经暴露和引用的服务。
* 2. 释放协议所占用的所有资源,比如连接和端口。
* 3. 协议在释放后,依然能暴露和引用新的服务。
*/ void destroy(); } /** * 扩展点接口的标识。 * 扩展点声明配置文件,格式修改。 * 以Protocol示例,配置文件META-INF/dubbo/com.xxx.Protocol内容: * 由 * com.foo.XxxProtocol * com.foo.YyyProtocol * 改成使用KV格式 * xxx=com.foo.XxxProtocol * yyy=com.foo.YyyProtocol * * 原因: * 当扩展点的static字段或方法签名上引用了三方库, * 如果三方库不存在,会导致类初始化失败, * Extension标识Dubbo就拿不到了,异常信息就和配置信息对应不起来。 * * 比如: * Extension("mina")加载失败, * 当用户配置使用mina时,就会报找不到扩展点mina, * 而不是报加载扩展点失败,等难以定位具体问题的错误。 * * @author william.liangf * @author ding.lid * @export */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface SPI { /** * default extension name * * 默认拓展名 */ String value() default ""; } // 配置文件 com.alibaba.dubbo.rpc.Protocol 中的内容 dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol ``` value 就是该 Protocol 接口 的实现类 DubboProtocol,这样就做到了 SPI 扩展。 ### ExtensionLoader ExtensionLoader 扩展加载器,这是 dubbo 实现 SPI 扩展机制 的核心,几乎所有实现的逻辑都被封装在 ExtensionLoader 中,其源码如下。 ```java /** * 拓展加载器,Dubbo使用的扩展点获取 *
    *
  • 自动注入关联扩展点。
  • *
  • 自动Wrap上扩展点的Wrap类。
  • *
  • 缺省获得的的扩展点是一个Adaptive Instance。
  • *
* * 另外,该类同时是 ExtensionLoader 的管理容器,例如 {@link #EXTENSION_INSTANCES} 、{@link #EXTENSION_INSTANCES} 属性。 */ @SuppressWarnings("deprecation") public class ExtensionLoader { private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class); private static final String SERVICES_DIRECTORY = "META-INF/services/"; private static final String DUBBO_DIRECTORY = "META-INF/dubbo/"; private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/"; private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*"); // ============================== 静态属性 ============================== /** * 拓展加载器集合 * * key:拓展接口 */ private static final ConcurrentMap, ExtensionLoader> EXTENSION_LOADERS = new ConcurrentHashMap, ExtensionLoader>(); /** * 拓展实现类集合 * * key:拓展实现类 * value:拓展对象。 * * 例如,key 为 Class * value 为 AccessLogFilter 对象 */ private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap, Object>(); // ============================== 对象属性 ============================== /** * 拓展接口。 * 例如,Protocol */ private final Class type; /** * 对象工厂 * * 用于调用 {@link #injectExtension(Object)} 方法,向拓展对象注入依赖的属性。 * * 例如,StubProxyFactoryWrapper 中有 `Protocol protocol` 属性。 */ private final ExtensionFactory objectFactory; /** * 缓存的拓展名与拓展类的映射。 * * 和 {@link #cachedClasses} 的 KV 对调。 * * 通过 {@link #loadExtensionClasses} 加载 */ private final ConcurrentMap, String> cachedNames = new ConcurrentHashMap, String>(); /** * 缓存的拓展实现类集合。 * * 不包含如下两种类型: * 1. 自适应拓展实现类。例如 AdaptiveExtensionFactory * 2. 带唯一参数为拓展接口的构造方法的实现类,或者说拓展 Wrapper 实现类。例如,ProtocolFilterWrapper 。 * 拓展 Wrapper 实现类,会添加到 {@link #cachedWrapperClasses} 中 * * 通过 {@link #loadExtensionClasses} 加载 */ private final Holder>> cachedClasses = new Holder>>(); /** * 拓展名与 @Activate 的映射 * * 例如,AccessLogFilter。 * * 用于 {@link #getActivateExtension(URL, String)} */ private final Map cachedActivates = new ConcurrentHashMap(); /** * 缓存的拓展对象集合 * * key:拓展名 * value:拓展对象 * * 例如,Protocol 拓展 * key:dubbo value:DubboProtocol * key:injvm value:InjvmProtocol * * 通过 {@link #loadExtensionClasses} 加载 */ private final ConcurrentMap> cachedInstances = new ConcurrentHashMap>(); /** * 缓存的自适应( Adaptive )拓展对象 */ private final Holder cachedAdaptiveInstance = new Holder(); /** * 缓存的自适应拓展对象的类 * * {@link #getAdaptiveExtensionClass()} */ private volatile Class cachedAdaptiveClass = null; /** * 缓存的默认拓展名 * * 通过 {@link SPI} 注解获得 */ private String cachedDefaultName; /** * 创建 {@link #cachedAdaptiveInstance} 时发生的异常。 * * 发生异常后,不再创建,参见 {@link #createAdaptiveExtension()} */ private volatile Throwable createAdaptiveInstanceError; /** * 拓展 Wrapper 实现类集合 * * 带唯一参数为拓展接口的构造方法的实现类 * * 通过 {@link #loadExtensionClasses} 加载 */ private Set> cachedWrapperClasses; /** * 拓展名 与 加载对应拓展类发生的异常 的 映射 * * key:拓展名 * value:异常 * * 在 {@link #loadFile(Map, String)} 时,记录 */ private Map exceptions = new ConcurrentHashMap(); private ExtensionLoader(Class type) { this.type = type; objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); } /** * 是否包含 @SPI 注解 * * @param type 类 * @param 泛型 * @return 是否包含 */ private static boolean withExtensionAnnotation(Class type) { return type.isAnnotationPresent(SPI.class); } /** * 根据拓展点的接口,获得拓展加载器 * * @param type 接口 * @param 泛型 * @return 加载器 */ @SuppressWarnings("unchecked") public static ExtensionLoader getExtensionLoader(Class type) { if (type == null) throw new IllegalArgumentException("Extension type == null"); // 必须是接口 if (!type.isInterface()) { throw new IllegalArgumentException("Extension type(" + type + ") is not interface!"); } // 必须包含 @SPI 注解 if (!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!"); } // 获得接口对应的拓展点加载器 ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type); if (loader == null) { EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type)); loader = (ExtensionLoader) EXTENSION_LOADERS.get(type); } return loader; } private static ClassLoader findClassLoader() { return ExtensionLoader.class.getClassLoader(); } public String getExtensionName(T extensionInstance) { return getExtensionName(extensionInstance.getClass()); } public String getExtensionName(Class extensionClass) { return cachedNames.get(extensionClass); } public List getActivateExtension(URL url, String key) { return getActivateExtension(url, key, null); } public List getActivateExtension(URL url, String[] values) { return getActivateExtension(url, values, null); } /** * 获得符合自动激活条件的拓展对象数组 */ public List getActivateExtension(URL url, String key, String group) { // 从 Dubbo URL 获得参数值 String value = url.getParameter(key); // 获得符合自动激活条件的拓展对象数组 return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group); } /** * 获得符合自动激活条件的拓展对象数组 */ public List getActivateExtension(URL url, String[] values, String group) { List exts = new ArrayList(); List names = values == null ? new ArrayList(0) : Arrays.asList(values); // 处理自动激活的拓展对象们 // 判断不存在配置 `"-name"` 。例如, ,代表移除所有默认过滤器。 if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) { // 获得拓展实现类数组 getExtensionClasses(); // 循环 for (Map.Entry entry : cachedActivates.entrySet()) { String name = entry.getKey(); Activate activate = entry.getValue(); if (isMatchGroup(group, activate.group())) { // 匹配分组 // 获得拓展对象 T ext = getExtension(name); if (!names.contains(name) // 不包含在自定义配置里。如果包含,会在下面的代码处理。 && !names.contains(Constants.REMOVE_VALUE_PREFIX + name) // 判断是否配置移除。例如 ,则 MonitorFilter 会被移除 && isActive(activate, url)) { // 判断是否激活 exts.add(ext); } } } // 排序 Collections.sort(exts, ActivateComparator.COMPARATOR); } // 处理自定义配置的拓展对象们。例如在 ,代表需要加入 DemoFilter (这个是笔者自定义的)。 List usrs = new ArrayList(); for (int i = 0; i < names.size(); i++) { String name = names.get(i); if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX) && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) { // 判断非移除的 // 将配置的自定义在自动激活的拓展对象们前面。例如, ,则 DemoFilter 就会放在默认的过滤器前面。 if (Constants.DEFAULT_KEY.equals(name)) { if (!usrs.isEmpty()) { exts.addAll(0, usrs); usrs.clear(); } } else { // 获得拓展对象 T ext = getExtension(name); usrs.add(ext); } } } // 添加到结果集 if (!usrs.isEmpty()) { exts.addAll(usrs); } return exts; } /** * 匹配分组 * * @param group 过滤的分组条件。若为空,无需过滤 * @param groups 配置的分组 * @return 是否匹配 */ private boolean isMatchGroup(String group, String[] groups) { // 为空,无需过滤 if (group == null || group.length() == 0) { return true; } // 匹配 if (groups != null && groups.length > 0) { for (String g : groups) { if (group.equals(g)) { return true; } } } return false; } /** * 是否激活,通过 Dubbo URL 中是否存在参数名为 `@Activate.value` ,并且参数值非空。 * * @param activate 自动激活注解 * @param url Dubbo URL * @return 是否 */ private boolean isActive(Activate activate, URL url) { String[] keys = activate.value(); if (keys.length == 0) { return true; } for (String key : keys) { for (Map.Entry entry : url.getParameters().entrySet()) { String k = entry.getKey(); String v = entry.getValue(); if ((k.equals(key) || k.endsWith("." + key)) && ConfigUtils.isNotEmpty(v)) { return true; } } } return false; } /** * 返回扩展点实例,如果没有指定的扩展点或是还没加载(即实例化)则返回null。 * 注意:此方法不会触发扩展点的加载。 * 一般应该调用{@link #getExtension(String)}方法获得扩展,这个方法会触发扩展点加载。 */ @SuppressWarnings("unchecked") public T getLoadedExtension(String name) { if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null"); Holder holder = cachedInstances.get(name); if (holder == null) { cachedInstances.putIfAbsent(name, new Holder()); holder = cachedInstances.get(name); } return (T) holder.get(); } /** * 返回已经加载的扩展点的名字。 * 一般应该调用 getSupportedExtensions() 方法获得扩展,这个方法会返回所有的扩展点。 */ public Set getLoadedExtensions() { return Collections.unmodifiableSet(new TreeSet(cachedInstances.keySet())); } /** * 返回指定名字的扩展对象。如果指定名字的扩展不存在,则抛异常 {@link IllegalStateException}. * * @param name 拓展名 * @return 拓展对象 */ @SuppressWarnings("unchecked") public T getExtension(String name) { if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null"); // 查找 默认的 拓展对象 if ("true".equals(name)) { return getDefaultExtension(); } // 从 缓存中 获得对应的拓展对象 Holder holder = cachedInstances.get(name); if (holder == null) { cachedInstances.putIfAbsent(name, new Holder()); holder = cachedInstances.get(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; } /** * 返回缺省的扩展,如果没有设置则返回null。 */ public T getDefaultExtension() { getExtensionClasses(); // 如果为 true ,不能继续调用 `#getExtension(true)` 方法,会形成死循环。 if (null == cachedDefaultName || cachedDefaultName.length() == 0 || "true".equals(cachedDefaultName)) { return null; } return getExtension(cachedDefaultName); } public boolean hasExtension(String name) { if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null"); try { return getExtensionClass(name) != null; } catch (Throwable t) { return false; } } public Set getSupportedExtensions() { Map> clazzes = getExtensionClasses(); return Collections.unmodifiableSet(new TreeSet(clazzes.keySet())); } /** * 返回缺省的扩展点名,如果没有设置缺省则返回null。 */ public String getDefaultExtensionName() { getExtensionClasses(); return cachedDefaultName; } /** * 编程方式添加新扩展点。 * * @param name 扩展点名 * @param clazz 扩展点类 * @throws IllegalStateException 要添加扩展点名已经存在。 */ public void addExtension(String name, Class clazz) { getExtensionClasses(); // load classes if (!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Input type " + clazz + "not implement Extension " + type); } if (clazz.isInterface()) { throw new IllegalStateException("Input type " + clazz + "can not be interface!"); } if (!clazz.isAnnotationPresent(Adaptive.class)) { if (StringUtils.isBlank(name)) { throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); } if (cachedClasses.get().containsKey(name)) { throw new IllegalStateException("Extension name " + name + " already existed(Extension " + type + ")!"); } cachedNames.put(clazz, name); cachedClasses.get().put(name, clazz); } else { if (cachedAdaptiveClass != null) { throw new IllegalStateException("Adaptive Extension already existed(Extension " + type + ")!"); } cachedAdaptiveClass = clazz; } } /** * 编程方式添加替换已有扩展点。 * * @param name 扩展点名 * @param clazz 扩展点类 * @throws IllegalStateException 要添加扩展点名已经存在。 * @deprecated 不推荐应用使用,一般只在测试时可以使用 */ @Deprecated public void replaceExtension(String name, Class clazz) { getExtensionClasses(); // load classes if (!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Input type " + clazz + "not implement Extension " + type); } if (clazz.isInterface()) { throw new IllegalStateException("Input type " + clazz + "can not be interface!"); } if (!clazz.isAnnotationPresent(Adaptive.class)) { if (StringUtils.isBlank(name)) { throw new IllegalStateException("Extension name is blank (Extension " + type + ")!"); } if (!cachedClasses.get().containsKey(name)) { throw new IllegalStateException("Extension name " + name + " not existed(Extension " + type + ")!"); } cachedNames.put(clazz, name); cachedClasses.get().put(name, clazz); cachedInstances.remove(name); } else { if (cachedAdaptiveClass == null) { throw new IllegalStateException("Adaptive Extension not existed(Extension " + type + ")!"); } cachedAdaptiveClass = clazz; cachedAdaptiveInstance.set(null); } } /** * 获得自适应拓展对象 * * @return 拓展对象 */ @SuppressWarnings("unchecked") public T getAdaptiveExtension() { // 从缓存中,获得自适应拓展对象 Object instance = cachedAdaptiveInstance.get(); if (instance == null) { // 若之前未创建报错, if (createAdaptiveInstanceError == null) { synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 创建自适应拓展对象 instance = createAdaptiveExtension(); // 设置到缓存 cachedAdaptiveInstance.set(instance); } catch (Throwable t) { // 记录异常 createAdaptiveInstanceError = t; throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t); } } } // 若之前创建报错,则抛出异常 IllegalStateException } else { throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } } return (T) instance; } /** * 获得拓展名不存在时的异常 * * @param name 拓展名 * @return 异常 */ private IllegalStateException findException(String name) { // 在 `#loadFile(...)` 方法中,加载时,发生异常 for (Map.Entry entry : exceptions.entrySet()) { if (entry.getKey().toLowerCase().contains(name.toLowerCase())) { return entry.getValue(); } } // 生成不存在该拓展类实现的异常。 StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " + name); int i = 1; for (Map.Entry entry : exceptions.entrySet()) { if (i == 1) { buf.append(", possible causes: "); } buf.append("\r\n("); buf.append(i++); buf.append(") "); buf.append(entry.getKey()); buf.append(":\r\n"); buf.append(StringUtils.toString(entry.getValue())); } return new IllegalStateException(buf.toString()); } /** * 创建拓展名的拓展对象,并缓存。 * * @param name 拓展名 * @return 拓展对象 */ @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); } // 注入依赖的属性 injectExtension(instance); // 创建 Wrapper 拓展对象 Set> wrapperClasses = cachedWrapperClasses; if (wrapperClasses != null && !wrapperClasses.isEmpty()) { for (Class wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type + ") could not be instantiated: " + t.getMessage(), t); } } /** * 注入依赖的属性 * * @param instance 拓展对象 * @return 拓展对象 */ private T injectExtension(T instance) { try { if (objectFactory != null) { for (Method method : instance.getClass().getMethods()) { if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { // setting && public 方法 // 获得属性的类型 Class pt = method.getParameterTypes()[0]; try { // 获得属性 String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; // 获得属性值 Object object = objectFactory.getExtension(pt, property); // 设置属性值 if (object != null) { method.invoke(instance, object); } } catch (Exception e) { logger.error("fail to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(), e); } } } } } catch (Exception e) { logger.error(e.getMessage(), e); } return instance; } private Class getExtensionClass(String name) { if (type == null) throw new IllegalArgumentException("Extension type == null"); if (name == null) throw new IllegalArgumentException("Extension name == null"); // 获得拓展实现类 Class clazz = getExtensionClasses().get(name); if (clazz == null) throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName() + "!"); return clazz; } /** * 获得拓展实现类数组 * * @return 拓展实现类数组 */ private Map> getExtensionClasses() { // 从缓存中,获得拓展实现类数组 Map> classes = cachedClasses.get(); if (classes == null) { synchronized (cachedClasses) { classes = cachedClasses.get(); if (classes == null) { // 从配置文件中,加载拓展实现类数组 classes = loadExtensionClasses(); // 设置到缓存中 cachedClasses.set(classes); } } } return classes; } /** * 加载拓展实现类数组 * * @return 拓展实现类数组 */ private Map> loadExtensionClasses() { // 通过 @SPI 注解,获得默认的拓展实现类名 final SPI defaultAnnotation = type.getAnnotation(SPI.class); if (defaultAnnotation != null) { String value = defaultAnnotation.value(); if ((value = value.trim()).length() > 0) { 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]; } } // 从配置文件中,加载拓展实现类数组 Map> extensionClasses = new HashMap>(); loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); loadFile(extensionClasses, DUBBO_DIRECTORY); loadFile(extensionClasses, SERVICES_DIRECTORY); return extensionClasses; } /** * 从一个配置文件中,加载拓展实现类数组。 * * @param extensionClasses 拓展类名数组 * @param dir 文件名 */ private void loadFile(Map> extensionClasses, String dir) { // 完整的文件名 String fileName = dir + type.getName(); try { Enumeration urls; // 获得文件名对应的所有文件数组 ClassLoader classLoader = findClassLoader(); if (classLoader != null) { urls = classLoader.getResources(fileName); } else { urls = ClassLoader.getSystemResources(fileName); } // 遍历文件数组 if (urls != null) { while (urls.hasMoreElements()) { java.net.URL url = urls.nextElement(); try { BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8")); try { String line; while ((line = reader.readLine()) != null) { // 跳过当前被注释掉的情况,例如 #spring=xxxxxxxxx final int ci = line.indexOf('#'); if (ci >= 0) line = line.substring(0, ci); line = line.trim(); if (line.length() > 0) { try { // 拆分,key=value 的配置格式 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) { // 判断拓展实现,是否实现拓展接口 Class clazz = Class.forName(line, true, classLoader); if (!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Error when load extension class(interface: " + type + ", class line: " + clazz.getName() + "), class " + clazz.getName() + "is not subtype of interface."); } // 缓存自适应拓展对象的类到 `cachedAdaptiveClass` if (clazz.isAnnotationPresent(Adaptive.class)) { if (cachedAdaptiveClass == null) { cachedAdaptiveClass = clazz; } else if (!cachedAdaptiveClass.equals(clazz)) { throw new IllegalStateException("More than 1 adaptive class found: " + cachedAdaptiveClass.getClass().getName() + ", " + clazz.getClass().getName()); } } else { // 缓存拓展 Wrapper 实现类到 `cachedWrapperClasses` try { clazz.getConstructor(type); Set> wrappers = cachedWrapperClasses; if (wrappers == null) { cachedWrapperClasses = new ConcurrentHashSet>(); wrappers = cachedWrapperClasses; } wrappers.add(clazz); // 缓存拓展实现类到 `extensionClasses` } catch (NoSuchMethodException e) { clazz.getConstructor(); // 未配置拓展名,自动生成。例如,DemoFilter 为 demo 。主要用于兼容 Java SPI 的配置。 if (name == null || name.length() == 0) { name = findAnnotationName(clazz); if (name == null || name.length() == 0) { if (clazz.getSimpleName().length() > type.getSimpleName().length() && clazz.getSimpleName().endsWith(type.getSimpleName())) { name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase(); } else { throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url); } } } // 获得拓展名,可以是数组,有多个拓展名。 String[] names = NAME_SEPARATOR.split(name); if (names != null && names.length > 0) { // 缓存 @Activate 到 `cachedActivates` 。 Activate activate = clazz.getAnnotation(Activate.class); if (activate != null) { cachedActivates.put(names[0], activate); } for (String n : names) { // 缓存到 `cachedNames` if (!cachedNames.containsKey(clazz)) { cachedNames.put(clazz, n); } // 缓存拓展实现类到 `extensionClasses` Class c = extensionClasses.get(n); if (c == null) { extensionClasses.put(n, clazz); } else if (c != clazz) { throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName()); } } } } } } } catch (Throwable t) { // 发生异常,记录到异常集合 IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t); exceptions.put(line, e); } } } // end of while read lines } finally { reader.close(); } } catch (Throwable t) { logger.error("Exception when load extension class(interface: " + type + ", class file: " + url + ") in " + url, t); } } // end of while urls } } catch (Throwable t) { logger.error("Exception when load extension class(interface: " + type + ", description file: " + fileName + ").", t); } } @SuppressWarnings("deprecation") private String findAnnotationName(Class clazz) { com.alibaba.dubbo.common.Extension extension = clazz.getAnnotation(com.alibaba.dubbo.common.Extension.class); if (extension == null) { String name = clazz.getSimpleName(); if (name.endsWith(type.getSimpleName())) { name = name.substring(0, name.length() - type.getSimpleName().length()); } return name.toLowerCase(); } return extension.value(); } /** * 创建自适应拓展对象 * * @return 拓展对象 */ @SuppressWarnings("unchecked") private T createAdaptiveExtension() { try { return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e); } } /** * @return 自适应拓展类 */ private Class getAdaptiveExtensionClass() { getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } return cachedAdaptiveClass = createAdaptiveExtensionClass(); } /** * 自动生成自适应拓展的代码实现,并编译后返回该类。 * * @return 类 */ 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); } /** * 自动生成自适应拓展的代码实现的字符串 * * @return 代码字符串 */ private String createAdaptiveExtensionClassCode() { StringBuilder codeBuidler = new StringBuilder(); // 遍历方法数组,判断有 @Adaptive 注解 Method[] methods = type.getMethods(); boolean hasAdaptiveAnnotation = false; for (Method m : methods) { if (m.isAnnotationPresent(Adaptive.class)) { hasAdaptiveAnnotation = true; break; } } // no need to generate adaptive class since there's no adaptive method found. // 完全没有Adaptive方法,则不需要生成Adaptive类 if (!hasAdaptiveAnnotation) throw new IllegalStateException("No adaptive method on extension " + type.getName() + ", refuse to create the adaptive class!"); // 生成代码:package 和 import codeBuidler.append("package " + type.getPackage().getName() + ";"); codeBuidler.append("\nimport " + ExtensionLoader.class.getName() + ";"); // 生成代码:类名 codeBuidler.append("\npublic class " + type.getSimpleName() + "$Adaptive" + " implements " + type.getCanonicalName() + " {"); // 循环方法 for (Method method : methods) { Class rt = method.getReturnType(); // 返回类型 Class[] pts = method.getParameterTypes(); // 参数类型数组 Class[] ets = method.getExceptionTypes(); // 异常类型数组 Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class); StringBuilder code = new StringBuilder(512); // 方法体的代码 // 非 @Adaptive 注解,生成代码:生成的方法为直接抛出异常。因为,非自适应的接口不应该被调用。 if (adaptiveAnnotation == null) { code.append("throw new UnsupportedOperationException(\"method ") .append(method.toString()).append(" of interface ") .append(type.getName()).append(" is not adaptive method!\");"); // @Adaptive 注解,生成方法体的代码 } else { // 寻找 Dubbo URL 参数的位置 int urlTypeIndex = -1; for (int i = 0; i < pts.length; ++i) { if (pts[i].equals(URL.class)) { urlTypeIndex = i; break; } } // found parameter in URL type // 有类型为URL的参数,生成代码:生成校验 URL 非空的代码 if (urlTypeIndex != -1) { // Null Point check String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");", urlTypeIndex); code.append(s); s = String.format("\n%s url = arg%d;", URL.class.getName(), urlTypeIndex); code.append(s); } // did not find parameter in URL type // 参数没有URL类型 else { String attribMethod = null; // find URL getter method // 找到参数的URL属性 。例如,Invoker 有 `#getURL()` 方法。 LBL_PTS: for (int i = 0; i < pts.length; ++i) { Method[] ms = pts[i].getMethods(); for (Method m : ms) { String name = m.getName(); if ((name.startsWith("get") || name.length() > 3) && Modifier.isPublic(m.getModifiers()) && !Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0 && m.getReturnType() == URL.class) { // pubic && getting 方法 urlTypeIndex = i; attribMethod = name; break LBL_PTS; } } } // 未找到,抛出异常。 if (attribMethod == null) { throw new IllegalStateException("fail to create adaptive class for interface " + type.getName() + ": not found url parameter or url attribute in parameters of method " + method.getName()); } // 生成代码:校验 URL 非空 // Null point check String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");", urlTypeIndex, pts[urlTypeIndex].getName()); code.append(s); s = String.format("\nif (arg%d.%s() == null) throw new IllegalArgumentException(\"%s argument %s() == null\");", urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod); code.append(s); // 生成 `URL url = arg%d.%s();` 的代码 s = String.format("%s url = arg%d.%s();", URL.class.getName(), urlTypeIndex, attribMethod); code.append(s); } String[] value = adaptiveAnnotation.value(); // value is not set, use the value generated from class name as the key // 没有设置Key,则使用“扩展点接口名的点分隔 作为Key if (value.length == 0) { char[] charArray = type.getSimpleName().toCharArray(); StringBuilder sb = new StringBuilder(128); for (int i = 0; i < charArray.length; i++) { if (Character.isUpperCase(charArray[i])) { if (i != 0) { sb.append("."); } sb.append(Character.toLowerCase(charArray[i])); } else { sb.append(charArray[i]); } } value = new String[]{sb.toString()}; } // 判断是否有 Invocation 参数 boolean hasInvocation = false; for (int i = 0; i < pts.length; ++i) { if (pts[i].getName().equals("com.alibaba.dubbo.rpc.Invocation")) { // 生成代码:校验 Invocation 非空 // Null Point check String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", i); code.append(s); // 生成代码:获得方法名 s = String.format("\nString methodName = arg%d.getMethodName();", i); code.append(s); // 标记有 Invocation 参数 hasInvocation = true; break; } } // 默认拓展名 String defaultExtName = cachedDefaultName; // 获得最终拓展名的代码字符串,例如: // 【简单】1. url.getParameter("proxy", "javassist") // 【复杂】2. url.getParameter(key1, url.getParameter(key2, defaultExtName)) String getNameCode = null; for (int i = value.length - 1; i >= 0; --i) { // 倒序的原因,因为是顺序获取参数,参见【复杂】2. 的例子 if (i == value.length - 1) { if (null != defaultExtName) { if (!"protocol".equals(value[i])) if (hasInvocation) // 当【有】 Invocation 参数时,使用 `URL#getMethodParameter()` 方法。 getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName); else // 当【非】 Invocation 参数时,使用 `URL#getParameter()` 方法。 getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName); else // 当属性名是 "protocol" ,使用 `URL#getProtocl()` 方法获取。 getNameCode = String.format("( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", defaultExtName); } else { if (!"protocol".equals(value[i])) if (hasInvocation) getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName); // 此处的 defaultExtName ,可以去掉的。 else getNameCode = String.format("url.getParameter(\"%s\")", value[i]); else getNameCode = "url.getProtocol()"; } } else { if (!"protocol".equals(value[i])) if (hasInvocation) getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName); else getNameCode = String.format("url.getParameter(\"%s\", %s)", value[i], getNameCode); else getNameCode = String.format("url.getProtocol() == null ? (%s) : url.getProtocol()", getNameCode); } } // 生成代码:获取参数的代码。例如:String extName = url.getParameter("proxy", "javassist"); code.append("\nString extName = ").append(getNameCode).append(";"); // check extName == null? String s = String.format("\nif(extName == null) " + "throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");", type.getName(), Arrays.toString(value)); code.append(s); // 生成代码:拓展对象,调用方法。例如 // `com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class) // .getExtension(extName);` 。 s = String.format("\n%s extension = (% 0) { codeBuidler.append(", "); } codeBuidler.append(pts[i].getCanonicalName()); codeBuidler.append(" "); codeBuidler.append("arg" + i); } codeBuidler.append(")"); if (ets.length > 0) { codeBuidler.append(" throws "); // 异常 for (int i = 0; i < ets.length; i++) { if (i > 0) { codeBuidler.append(", "); } codeBuidler.append(ets[i].getCanonicalName()); } } codeBuidler.append(" {"); codeBuidler.append(code.toString()); codeBuidler.append("\n}"); } // 生成类末尾的 `}` codeBuidler.append("\n}"); // 调试,打印生成的代码 if (logger.isDebugEnabled()) { logger.debug(codeBuidler.toString()); } return codeBuidler.toString(); } @Override public String toString() { return this.getClass().getName() + "[" + type.getName() + "]"; } } ```