spi是什么?
  简单来说spi就是service provider interface,比如你有三个接口,现在这个接口有三个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这个时候就需要spi了,主要根据指定的配置或默认配置,去找对应的实现类加载进来,然后用这个实现类的对象。

举个例子
  有一个接口A,A1/A2/A3分别是三个实现类,通过配置,接口A=A2,那么在系统运行的时候,会加载相关配置,用实现累A2来实例化对象来提供服务。
  spi机制的应用场景:插件扩展场景,比如说你开了一个给别人使用的开源框架,如果你想让别人自己写个插件,查到自己的开源框架里面,从而扩展这个功能,这个时候spi思想就用上了。

java spi 思想体现

spi经典的思想体现,大家都在用,比如说JDBC;
java定义了一个JDBC接口,并没有提供jdbc的实现类。

但是实际上项目跑的时候需要jdbc接口哪些实现类呢?一般来说,我们要根据自己的使用的何种数据库决定,比如mysql,你就将mysql-jdbc-connector.jar引入,orcal,就需要将orcal-jdbc-connector.jar。
  在系统跑的时候碰到你使用的JDBC接口,他会在底层使用你引入的那个jar中提供的实现类。

Dubbo中spi思想

dubbo也用了spi思想,但是没有使用jdk中的spi机制,是自己实现的一套spi机制。

Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

Protocol 接口在系统运行的时候,Dubbo会判断一下应该选中Protocol接口中的哪个实现类来实现实例化对象。

它会找一个你配置的Protocol实现类,将其加载到JVM中,然后实例化对象,就用你配置的Protocol实现类就可以了。

上述代码就是Dubbo中普遍使用的,就是对很多组件都保留一个接口和多个实现类,然后在系统运行的时候动态的根据配置去找队友的实现类,如果没有配置,那就走默认的实现就好了,没有问题。

@SPI("dubbo")  
public interface Protocol {  
      
    int getDefaultPort();  
  
    @Adaptive  
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;  
  
    @Adaptive  
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;  

    void destroy();  
  
}

在 dubbo 自己的 jar 里,在/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol文件中:

dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol

所以说这就看到dubbo的spi机制是怎么玩的了,其实就是Protocol接口。