spi
SPI 的缺点
JDK 标准的 SPI 会一次性加载实例化扩展点的所有实现,JDK 启动的时候会一次性全部加载。
1如果有的扩展点实现初始化很耗时或者如果有些实现类并没有用到, 会很浪费资源。
2如果扩展点加载失败,会导致调用方报错,而且这个错误很难定位到。
dubbo spi
1 | Protocol p = ExtensionLoader.getExtensionLoader(xxx.class).getAdaptiveExtension(); |
protocol
会在运行的时候判断一下应该选用这个Protocol接口的哪个实现类来实例化对象。
动态的根据配置去找到对应的实现类。如果你没有配置,那就走默认的实现类。
1 | @SPI("dubbo") |
@SPI(“dubbo”)
:通过 SPI 机制来提供实现类,实现类是通过 dubbo 作为默认 key 去配置文件里找到的,配置文件名称与接口全限定名一样的,通过 dubbo 作为 key 可以找到默认的实现类就是 org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
@Adaptive
:如果想要动态替换掉默认的实现类,需要使用 @Adaptive 。表示动态代理实现。在运行的时候会针对 Protocol 生成代理类
,这个代理类的那俩方法里面会有代理代码
,代理代码会在运行的时候动态根据 url 中的 protocol 来获取那个 key,默认是 dubbo,自己指定则获取相应的实现。
扩展dubbo组件
step1
step2
step3
1 | public class App |
实现原理探析
getExtension方法获取一个SPI接口的扩展类实例的流程: 分为解析配置文件、加载并缓存扩展类、创建并加工(属性注入与层层包装)扩展类实例 几个步骤。
通过getAdaptiveExtension方法的流程可以发现,要想获得一个SPI接口的自适应扩展类实例,有2种方式:
1在SPI接口的配置文件中配置具有@Adaptive注解的扩展类,在执行解析SPI接口配置文件方法getExtensionClasses时,它会调用loadClass方法,该方法判断扩展类是否具有@Adaptive注解,如果有,则将该类Class缓存到ExtensionLoader的字段“cachedAdaptiveClass”中,然后直接实例化该Class的实例并进行自动装配;
2如果未配置@Adaptive修饰的扩展类,则Dubbo会使用字节码技术创建一个自适应扩展类,前提是SPI接口上至少有一个被@Adaptive注解的方法;
todo
本文链接: https://satyrswang.github.io/2021/01/31/dubbo-spi/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!