甜腻的嘴角|Dubbo如何通过SPI提高框架的可扩展性?( 二 )

extensionLoader = ExtensionLoader.getExtensionLoader(Car.class);Car car = extensionLoader.getExtension("benz");car.getBrand();}}@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE})public @interface SPI {String value() default "";}@SPI标记接口是一个Dubbo SPI接口 , 即是一个扩展点 , value属性可以指定默认实现
Dubbo 并未使用 Java 原生的 SPI 机制 , 而是对其进行了增强 , 使其能够更好的满足需求 。 Dubbo SPI的优点如下

  1. JDK标准的SPI会一次性实例化扩展点的所有实现 。 而Dubbo SPI能实现按需加载
  2. Dubbo SPI增加了对扩展点Ioc和Aop的支持
Dubbo SPI的实现步骤如下
  1. 定义接口及其对应的实现类 , 接口上加@SPI注解 , 表明这是一个扩展类
  2. 在META-INF/services目录下创建以接口全路径命名的文件
  3. 文件内容为实现类的全路径名
  4. 在代码中通过ExtensionLoader加载具体的实现类
Dubbo SPI 扩展点的特性自动包装扩展类的构造函数是一个扩展点 , 则认为这个类是一个Wrapper类 , 即AOP
用例子演示一下
@SPIpublic interface Car {void getBrand();}public class BenzCar implements Car {@Overridepublic void getBrand() {System.out.println("benz");}}public class CarWrapper implements Car {private Car car;public CarWrapper(Car car) {this.car = car;}@Overridepublic void getBrand() {System.out.println("start");car.getBrand();System.out.println("end");}}org.apache.dubbo.aop.Car内容如下(resources\META-INF\services目录下)
benz=org.apache.dubbo.aop.BenzCarorg.apache.dubbo.aop.CarWrapper测试类
public class DubboSpiAopDemo {public static void main(String[] args) {ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(Car.class);Car car = extensionLoader.getExtension("benz");// start// benz// endcar.getBrand();}}BenzCar是一个扩展类 , CarWrapper是一个包装类 , 当获取BenzCar的时候实际获取的是被CarWrapper包装后的对象 , 类似代理模式
自动加载如果一个扩展类是另一个扩展类的成员变量 , 并且拥有set方法 , 框架会自动注入这个扩展点的实例 , 即IOC 。 先定义2个扩展点
org.apache.dubbo.ioc.Car(resources\META-INF\services目录下)
benz=org.apache.dubbo.ioc.BenzCarorg.apache.dubbo.ioc.Wheel(resources\META-INF\services目录下)
benz=org.apache.dubbo.ioc.BenzWheel@SPIpublic interface Wheel {void getBrandByUrl();}public class BenzWheel implements Wheel {@Overridepublic void getBrandByUrl() {System.out.println("benzWheel");}}@SPIpublic interface Car {void getBrandByUrl();}public class BenzCar implements Car {private Wheel wheel;public void setWheel(Wheel wheel) {this.wheel = wheel;}@Overridepublic void getBrandByUrl() {System.out.println("benzCar");wheel.getBrandByUrl();}}测试demo
public class DubboSpiIocDemo {public static void main(String[] args) {ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(Car.class);Car car = extensionLoader.getExtension("benz");car.getBrandByUrl();}}


推荐阅读