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 进行了改进。
- JDK 标准的 SPI 只能通过遍历来查找扩展点和实例化,有可能导致一次性加载所有的扩展点,如果不是所有的扩展点都被用到,就会导致资源的浪费。dubbo 每个扩展点都有多种实现,例如:com.alibaba.dubbo.rpc.Protocol 接口有 InjvmProtocol、DubboProtocol、RmiProtocol、HttpProtocol、HessianProtocol 等实现,如果只是用到其中一个实现,可是加载了全部的实现,会导致资源的浪费。
- 对配置文件中扩展实现的格式的修改,例如,META-INF/dubbo/com.xxx.Protocol 里的 com.foo.XxxProtocol 格式 改为了 xxx = com.foo.XxxProtocol 这种以键值对的形式,这样做的目的是为了让我们更容易的定位到问题。比如,由于第三方库不存在,无法初始化,导致无法加载扩展点(“A”),当用户配置使用 A 时,dubbo 就会报无法加载扩展点的错误,而不是报哪些扩展点的实现加载失败以及错误原因,这是因为原来的配置格式没有记录扩展名的 id,导致 dubbo 无法抛出较为精准的异常,这会加大排查问题的难度。所以改成 key-value 的形式来进行配置。
- dubbo 的 SPI 机制增加了对 IOC、AOP 的支持,一个扩展点可以直接通过 setter 注入到其他扩展点。
下面我们看一下 Dubbo 的 SPI 扩展机制实现的结构目录。

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,源码如下。
/*** 协议接口* Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。*/@SPI("dubbo")public interface Protocol {/*** Get default port when user doesn't config the port.*/int getDefaultPort();/*** 暴露远程服务:* 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>* 2. export() 必须是幂等的,也就是暴露同一个 URL 的 Invoker 两次,和暴露一次没有区别。<br>* 3. export() 传入的 Invoker 由框架实现并传入,协议不需要关心。<br>** @param <T> 服务的类型* @param invoker 服务的执行体* @return exporter 暴露服务的引用,用于取消暴露* @throws RpcException 当暴露服务出错时抛出,比如端口已占用*/@Adaptive<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;/*** 引用远程服务:<br>* 1. 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。<br>* 2. refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求。<br>* 3. 当 url 中有设置 check=false 时,连接失败不能抛出异常,并内部自动恢复。<br>** @param <T> 服务的类型* @param type 服务的类型* @param url 远程服务的URL地址* @return invoker 服务的本地代理* @throws RpcException 当连接服务提供方失败时抛出*/@Adaptive<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;/*** 释放协议:<br>* 1. 取消该协议所有已经暴露和引用的服务。<br>* 2. 释放协议所占用的所有资源,比如连接和端口。<br>* 3. 协议在释放后,依然能暴露和引用新的服务。<br>*/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 中,其源码如下。
/*** 拓展加载器,Dubbo使用的扩展点获取* <ul>* <li>自动注入关联扩展点。</li>* <li>自动Wrap上扩展点的Wrap类。</li>* <li>缺省获得的的扩展点是一个Adaptive Instance。</li>* </ul>** 另外,该类同时是 ExtensionLoader 的管理容器,例如 {@link #EXTENSION_INSTANCES} 、{@link #EXTENSION_INSTANCES} 属性。*/@SuppressWarnings("deprecation")public class ExtensionLoader<T> {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<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();/*** 拓展实现类集合** key:拓展实现类* value:拓展对象。** 例如,key 为 Class<AccessLogFilter>* value 为 AccessLogFilter 对象*/private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();// ============================== 对象属性 ==============================/*** 拓展接口。* 例如,Protocol*/private final Class<?> type;/*** 对象工厂** 用于调用 {@link #injectExtension(Object)} 方法,向拓展对象注入依赖的属性。** 例如,StubProxyFactoryWrapper 中有 `Protocol protocol` 属性。*/private final ExtensionFactory objectFactory;/*** 缓存的拓展名与拓展类的映射。** 和 {@link #cachedClasses} 的 KV 对调。** 通过 {@link #loadExtensionClasses} 加载*/private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();/*** 缓存的拓展实现类集合。** 不包含如下两种类型:* 1. 自适应拓展实现类。例如 AdaptiveExtensionFactory* 2. 带唯一参数为拓展接口的构造方法的实现类,或者说拓展 Wrapper 实现类。例如,ProtocolFilterWrapper 。* 拓展 Wrapper 实现类,会添加到 {@link #cachedWrapperClasses} 中** 通过 {@link #loadExtensionClasses} 加载*/private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();/*** 拓展名与 @Activate 的映射** 例如,AccessLogFilter。** 用于 {@link #getActivateExtension(URL, String)}*/private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();/*** 缓存的拓展对象集合** key:拓展名* value:拓展对象** 例如,Protocol 拓展* key:dubbo value:DubboProtocol* key:injvm value:InjvmProtocol** 通过 {@link #loadExtensionClasses} 加载*/private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();/*** 缓存的自适应( Adaptive )拓展对象*/private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();/*** 缓存的自适应拓展对象的类** {@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<Class<?>> cachedWrapperClasses;/*** 拓展名 与 加载对应拓展类发生的异常 的 映射** key:拓展名* value:异常** 在 {@link #loadFile(Map, String)} 时,记录*/private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();private ExtensionLoader(Class<?> type) {this.type = type;objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());}/*** 是否包含 @SPI 注解** @param type 类* @param <T> 泛型* @return 是否包含*/private static <T> boolean withExtensionAnnotation(Class<T> type) {return type.isAnnotationPresent(SPI.class);}/*** 根据拓展点的接口,获得拓展加载器** @param type 接口* @param <T> 泛型* @return 加载器*/@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 interface!");}// 必须包含 @SPI 注解if (!withExtensionAnnotation(type)) {throw new IllegalArgumentException("Extension type(" + type +") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");}// 获得接口对应的拓展点加载器ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);if (loader == null) {EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));loader = (ExtensionLoader<T>) 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<T> getActivateExtension(URL url, String key) {return getActivateExtension(url, key, null);}public List<T> getActivateExtension(URL url, String[] values) {return getActivateExtension(url, values, null);}/*** 获得符合自动激活条件的拓展对象数组*/public List<T> 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<T> getActivateExtension(URL url, String[] values, String group) {List<T> exts = new ArrayList<T>();List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);// 处理自动激活的拓展对象们// 判断不存在配置 `"-name"` 。例如,<dubbo:service filter="-default" /> ,代表移除所有默认过滤器。if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {// 获得拓展实现类数组getExtensionClasses();// 循环for (Map.Entry<String, Activate> 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) // 判断是否配置移除。例如 <dubbo:service filter="-monitor" />,则 MonitorFilter 会被移除&& isActive(activate, url)) { // 判断是否激活exts.add(ext);}}}// 排序Collections.sort(exts, ActivateComparator.COMPARATOR);}// 处理自定义配置的拓展对象们。例如在 <dubbo:service filter="demo" /> ,代表需要加入 DemoFilter (这个是笔者自定义的)。List<T> usrs = new ArrayList<T>();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)) { // 判断非移除的// 将配置的自定义在自动激活的拓展对象们前面。例如,<dubbo:service filter="demo,default,demo2" /> ,则 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<String, String> 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;}/*** 返回扩展点实例,如果没有指定的扩展点或是还没加载(即实例化)则返回<code>null</code>。* 注意:此方法不会触发扩展点的加载。* 一般应该调用{@link #getExtension(String)}方法获得扩展,这个方法会触发扩展点加载。*/@SuppressWarnings("unchecked")public T getLoadedExtension(String name) {if (name == null || name.length() == 0)throw new IllegalArgumentException("Extension name == null");Holder<Object> holder = cachedInstances.get(name);if (holder == null) {cachedInstances.putIfAbsent(name, new Holder<Object>());holder = cachedInstances.get(name);}return (T) holder.get();}/*** 返回已经加载的扩展点的名字。* 一般应该调用 getSupportedExtensions() 方法获得扩展,这个方法会返回所有的扩展点。*/public Set<String> getLoadedExtensions() {return Collections.unmodifiableSet(new TreeSet<String>(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<Object> holder = cachedInstances.get(name);if (holder == null) {cachedInstances.putIfAbsent(name, new Holder<Object>());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;}/*** 返回缺省的扩展,如果没有设置则返回<code>null</code>。*/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<String> getSupportedExtensions() {Map<String, Class<?>> clazzes = getExtensionClasses();return Collections.unmodifiableSet(new TreeSet<String>(clazzes.keySet()));}/*** 返回缺省的扩展点名,如果没有设置缺省则返回<code>null</code>。*/public String getDefaultExtensionName() {getExtensionClasses();return cachedDefaultName;}/*** 编程方式添加新扩展点。** @param name 扩展点名* @param clazz 扩展点类* @throws IllegalStateException 要添加扩展点名已经存在。*/public void addExtension(String name, Class<?> clazz) {getExtensionClasses(); // load classesif (!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 不推荐应用使用,一般只在测试时可以使用*/@Deprecatedpublic void replaceExtension(String name, Class<?> clazz) {getExtensionClasses(); // load classesif (!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<String, IllegalStateException> 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<String, IllegalStateException> 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<Class<?>> 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<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;}/*** 加载拓展实现类数组** @return 拓展实现类数组*/private Map<String, Class<?>> 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<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);loadFile(extensionClasses, DUBBO_DIRECTORY);loadFile(extensionClasses, SERVICES_DIRECTORY);return extensionClasses;}/*** 从一个配置文件中,加载拓展实现类数组。** @param extensionClasses 拓展类名数组* @param dir 文件名*/private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {// 完整的文件名String fileName = dir + type.getName();try {Enumeration<java.net.URL> 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=xxxxxxxxxfinal 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<Class<?>> wrappers = cachedWrapperClasses;if (wrappers == null) {cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();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 和 importcodeBuidler.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 checkString 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 checkString 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,则使用“扩展点接口名的点分隔 作为Keyif (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 checkString 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 ,可以去掉的。elsegetNameCode = String.format("url.getParameter(\"%s\")", value[i]);elsegetNameCode = "url.getProtocol()";}} else {if (!"protocol".equals(value[i]))if (hasInvocation)getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);elsegetNameCode = String.format("url.getParameter(\"%s\", %s)", value[i], getNameCode);elsegetNameCode = 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 = (%<s)%s.getExtensionLoader(%s.class).getExtension(extName);",type.getName(), ExtensionLoader.class.getSimpleName(), type.getName());code.append(s);// return statementif (!rt.equals(void.class)) {code.append("\nreturn ");}s = String.format("extension.%s(", method.getName());code.append(s);for (int i = 0; i < pts.length; i++) {if (i != 0)code.append(", ");code.append("arg").append(i);}code.append(");");}// 生成方法codeBuidler.append("\npublic " + rt.getCanonicalName() + " " + method.getName() + "(");for (int i = 0; i < pts.length; i++) {if (i > 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();}@Overridepublic String toString() {return this.getClass().getName() + "[" + type.getName() + "]";}}
