SPI什么是SPI?SPI是缩写。全称是ServiceProviderInterface。Java本身提供了一套SPI机制。在文件中,服务加载器读取配置文件并加载实现类,这样实现类就可以在运行时为接口动态替换,这也是很多框架组件实现扩展功能的一种手段。今天,DubboSPI机制和JavaSPI有点不同。Dubbo没有使用Java原生的SPI机制,而是对其进行了改进和增强,使得Dubbo可以方便地进行功能扩展。要学习一些东西,你必须带着问题去学习。先问几个问题,再看一下1.什么是SPI(开头有说明)2.DubboSPI和Java原生有什么区别3.这两个实现怎么写JavaSPI是怎么实现的先定义一个接口:publicinterfaceCar{voidstartUp();}然后创建两个实现Car接口的类println("Thetrainstarted");}}然后在项目META-INF/services文件夹下创建一个名为com.example.demo.spi.Car的完全限定接口。在文件内容中写上实现类的完全限定名,如下:com.example.demo.spi.Traincom.example.demo.spi.Truck最后写一段测试代码:publicclassJavaSPITest{@TestpublicvoidtestCar(){ServiceLoaderserviceLoader=ServiceLoader.load(Car.class);serviceLoader.forEach(Car::startUp);}}执行后输出:ThetrainstartedThetruckstartedDubboSPIDubbo是如何实现的?Dubbo使用的SPI并不是Java原生的,而是一种新的实现。它的主要逻辑在ExtensionLoader类中,逻辑并不难。后面再说,看看怎么用。它与Java没有太大区别。基于前面的例子,接口类需要注解@SPI:@SPIpublicinterfaceCar{voidstartUp();}实现类不需要改配置文件,需要放在META-INF/dubbo下。配置写法有些不同,直接看代码:train=com.example.demo.spi.Traintruck=com.example.demo.spi.Truck是最后的测试类,先看代码:publicclassJavaSPITest{@TestpublicvoidtestCar(){ExtensionLoaderextensionLoader=ExtensionLoader.getExtensionLoader(Car.class);Carcar=extensionLoader.getExtension("train");car.startUp();}}执行结果:常用注解@SPI在trainstartedDubbo中SPI被标记为扩展接口@Adaptive自适应扩展实现类标记@Activate自动激活条件标记总结一下两者的区别:使用上的区别Dubbo使用ExtensionLoader而不是ServiceLoader,它的主要逻辑都封装在这个类中,配置文件存放目录不同,Java在META-INF/services中,Dubbo在META-INF/dubbo中,META-INF/dubbo/internalJavaSPI会一次性实例化所有扩展点的实现。如果有扩展实现,初始化会比较费时,不会使用,会造成大量的资源浪费。DubboSPI增加了对扩展点IOC和AOP的支持。一个扩展点可以直接setter注入到其他扩展点。JavaSPI加载过程失败,扩展点的名称不可用。例如:JDK标准的ScriptEngine,getName()获取脚本类型的名称。如果RubyScriptEngine加载RubyScriptEngine类失败是因为它依赖的jruby.jar不存在,则不会提示此失败原因。当用户执行ruby脚本时,会报NoSupportruby??,并不是真正失败的原因。前面三个问题都回答了吗?DubboSPI源码分析是不是很简单DubboSPI是通过ExtensionLoader的getExtensionLoader方法获取一个ExtensionLoader实例,然后通过ExtensionLoader的getExtension方法获取扩展类对象。其中,getExtensionLoader方法用于从缓存中获取扩展类对应的ExtensionLoader。如果没有缓存,则新建一个实例,直接添加代码:publicTgetExtension(Stringname){if(name==null||name.length()==0){thrownewIllegalArgumentException("Extensionname==null");}if("true".equals(name)){//获取默认的扩展实现类returnDefaultExtension();}//用来持有目标对象Holder