首页 > 数据库 > 数据库开发技术 > 一文让你读懂 Dubbo 中的 SPI 扩展机制

Java SPI (Service Provider Interface)

插件式架构(Plug-in architecture)




adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactoryspi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactoryspring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

@SPI (注解在类上) : @SPI 注解标识了接口是一个扩展点 , 属性 value 用来指定默认适配扩展点的名称。
@Activate (注解在类型和方法上) : @Activate 注解在扩展点的实现类上 ,表示了一个扩展类被获取到的的条件,符合条件就被获取,不符合条件就不获取 ,根据 @Activate 中的 group 、 value 属性来过滤 。具体参考 ExtensionLoader 中的 getActivateExtension 函数。
@Adaptive (注解在类型和方法上) : @Adaptive 注解在类上 , 这个类就是缺省的适配扩展。@Adaptive 注解在扩展点 Interface 的方法上时 , dubbo 动态的生成一个这个扩展点的适配扩展类(生成代码 ,动态编译实例化 Class ),名称为 扩展点 Interface 的简单类名 + $Adaptive ,例如 :ProxyFactory$Adpative 。这么做的目的是为了在运行时去适配不同的扩展实例 , 在运行时通过传入的 URL 类型的参数或者内部含有获取 URL 方法的参数 ,从 URL 中获取到要使用的扩展类的名称 ,再去根据名称加载对应的扩展实例 ,用这个扩展实例对象调用相同的方法 。如果运行时没有适配到运行的扩展实例 , 那么就使用 @SPI 注解缺省指定的扩展。通过这种方式就实现了运行时去适配到对应的扩展。运行时动态生成的适配扩展类代码 :
package com.alibaba.dubbo.rpc;import com.alibaba.dubbo.common.extension.ExtensionLoader;public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {public void destroy() {throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");}public int getDefaultPort() {throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");}public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {if (arg1 == null) throw new IllegalArgumentException("url == null");com.alibaba.dubbo.common.URL url = arg1;// 从 URL 中获取扩展名称 , "dubbo" 是从 ExtensionLoader 对象中的 cachedDefaultName// 属性获取到的 , cachedDefaultName 是扩展点上 @SPI 注解中 value 属性指定的String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");// 通过扩展名称获取扩展实例对象 , 调用扩展实例对象的相同方法com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);return extension.refer(arg0, arg1);}public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.Invoker {if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");if (arg0.getUrl() == null)throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();// 从 URL 中获取扩展名称String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");// 通过扩展名称获取扩展实例对象 , 调用扩展实例对象的相同方法com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);return extension.export(arg0);}}
package com.alibaba.dubbo.rpc;import com.alibaba.dubbo.common.extension.ExtensionLoader;public class ProxyFactory$Adpative implements com.alibaba.dubbo.rpc.ProxyFactory {public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.Invoker {if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");if (arg0.getUrl() == null)throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();// 从 URL 中获取扩展名称String extName = url.getParameter("proxy", "javassist");if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");// 通过扩展名称获取扩展实例对象 , 调用扩展实例对象的相同方法com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);return extension.getProxy(arg0);}public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2) throws java.lang.Object {if (arg2 == null) throw new IllegalArgumentException("url == null");com.alibaba.dubbo.common.URL url = arg2;// 从 URL 中获取扩展名称String extName = url.getParameter("proxy", "javassist");if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");// 通过扩展名称获取扩展实例对象 , 调用扩展实例对象的相同方法com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension(extName);return extension.getInvoker(arg0, arg1, arg2);}}
ExtensionLoader.getExtensionLoader(Xxx.class).getExtension(extName);

Class<?> type;ExtensionFactory objectFactory;ConcurrentMap<Class<?>, String> cachedNames;Holder<Map<String, Class<?>>> cachedClasses;Map<String, Activate> cachedActivates;Class<?> cachedAdaptiveClass;ConcurrentMap<String, Holder<Object>> cachedInstances;String cachedDefaultName;Holder<Object> cachedAdaptiveInstance;Throwable createAdaptiveInstanceError;Set<Class<?>> cachedWrapperClasses;Map<String, IllegalStateException> exceptions;
com.alibaba.dubbo.cache.CacheFactorycom.alibaba.dubbo.common.compiler.Compilercom.alibaba.dubbo.common.extension.ExtensionFactorycom.alibaba.dubbo.common.logger.LoggerAdaptercom.alibaba.dubbo.common.serialize.Serializationcom.alibaba.dubbo.common.status.StatusCheckercom.alibaba.dubbo.common.store.DataStorecom.alibaba.dubbo.common.threadpool.ThreadPoolcom.alibaba.dubbo.container.Containercom.alibaba.dubbo.container.page.PageHandlercom.alibaba.dubbo.monitor.MonitorFactorycom.alibaba.dubbo.registry.RegistryFactorycom.alibaba.dubbo.remoting.Codec2com.alibaba.dubbo.remoting.Dispatchercom.alibaba.dubbo.remoting.exchange.Exchangercom.alibaba.dubbo.remoting.http.HttpBindercom.alibaba.dubbo.remoting.p2p.Networkercom.alibaba.dubbo.remoting.telnet.TelnetHandlercom.alibaba.dubbo.remoting.Transportercom.alibaba.dubbo.remoting.zookeeper.ZookeeperTransportercom.alibaba.dubbo.rpc.cluster.Clustercom.alibaba.dubbo.rpc.cluster.ConfiguratorFactorycom.alibaba.dubbo.rpc.cluster.LoadBalancecom.alibaba.dubbo.rpc.cluster.Mergercom.alibaba.dubbo.rpc.cluster.RouterFactorycom.alibaba.dubbo.rpc.Filtercom.alibaba.dubbo.rpc.InvokerListenercom.alibaba.dubbo.rpc.Protocolcom.alibaba.dubbo.rpc.protocol.thrift.ClassNameGeneratorcom.alibaba.dubbo.rpc.ProxyFactorycom.alibaba.dubbo.validation.Validation

原文作者:DevXTalk;如有侵权,请联系管理员删除。