dubbo spi 讲解分析

SPI

什么是 SPI

Service Provider Interface , 服务提供接口。

JDK SPI

Java 的 spi 机制,是去扫描 /META-INF/service/ 的接口名文件,并获取文件中的值。以 mysql 的驱动类来为案例。

用编辑器打开对应文件


ServiceLoader<Command> serviceLoader=ServiceLoader.load(Command.class);
for(Command command:serviceLoader){
  // 循环执行
  command.execute();  
}  

这里用到了 类的上下文加载器进下加载。

Java 通过 迭代器,循环加载对应文件中的类。

Dubbo SPI

途径:ExtensionLoader.getExtension(String name) 实现路径:

  • getExtensionLoader(Class<T> type) 就是为该接口 new 一个 ExtensionLoader,然后缓存起来。

  • getAdaptiveExtension() 获取一个扩展类,如果 @Adaptive 注解在类上就是一个装饰类;如果注解在方法上就是一个动态代理类,例如 Protocol$Adaptive 对象。

  • getExtension(String name) 获取一个指定对象。

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
   // 删除部分非空判断代码

   // 先判断扩展类是否已经存在
   ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
   if (loader == null)
       // 缓存 interface 对应的 dubbo spi 扩展加载类
       EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
       loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
  }
   return loader;
}

private ExtensionLoader(Class<?> type) {
       this.type = type;
   // 创建工厂,即 dubbo 的 IOC 输出中心,两个实现类 [SpiExtensionFactory,SpringExtensionFactory]
       objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
  }

public T getExtension(String name) {
   // 删除部分代码
   // 获取一个实体类,其中持有一个 volatile 的 interface 实现类对象,保证内存可见性
   Holder<Object> holder = cachedInstances.get(name);
   if (holder == null) {
       cachedInstances.putIfAbsent(name, new Holder<Object>());
       holder = cachedInstances.get(name);
  }
   Object instance = holder.get();
   if (instance == null) {
       synchronized (holder) {
           instance = holder.get();
           if (instance == null) {
          // 创建一个 interface 的实例对象
               instance = createExtension(name);
               holder.set(instance);
          }
      }
  }
   return (T) instance;
}

private T createExtension(String name) {
    // 获取对应的 name 的 class 加载类
       Class<?> clazz = getExtensionClasses().get(name);
    // 省略部分代码
       try {
           // 缓存对应是否存在
           T instance = (T) EXTENSION_INSTANCES.get(clazz);
           if (instance == null) {
               EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
               instance = (T) EXTENSION_INSTANCES.get(clazz);
          }
           // 注入对象
           injectExtension(instance);
           Set<Class<?>> wrapperClasses = cachedWrapperClasses;
           if (wrapperClasses != null && wrapperClasses.size() > 0) {
               for (Class<?> wrapperClass : wrapperClasses) {
                   // 构造器注入,,,IOC
                   instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
              }
          }
           return instance;
      } catch (Throwable t) {
           // 异常处理
      }
  }

private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
 // 获取方法名是 set 的属性,进下属性注入,,即 IOC
               if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {
Class<?> pt = method.getParameterTypes()[0];
try {
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("fail to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}

ExtensionLoader.getExtensionLoader(Class<T> type)

ExtensionLoader.getExtensionLoader(Container.class) -->this.type = type; -->objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() -->this.type = type; -->objectFactory =null;

getExtension(String name) 核心调用链如下

getExtension(String name)

//指定对象缓存在cachedInstances;get出来的对象wrapper对象,例如protocol就ProtocolFilterWrapper和ProtocolListenerWrapper其中一个。

-->createExtension(String name) -->getExtensionClasses() -->injectExtension(T instance)//dubbo的IOC反转控制,就是从spi和spring里面提取对象赋值。 -->objectFactory.getExtension(pt, property) -->SpiExtensionFactory.getExtension(type, name) -->ExtensionLoader.getExtensionLoader(type) -->loader.getAdaptiveExtension() -->SpringExtensionFactory.getExtension(type, name) -->context.getBean(name) -->injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance))//AOP的简单设计

getAdaptiveExtension()

-->getAdaptiveExtension()//为cachedAdaptiveInstance赋值 -->createAdaptiveExtension() -->getAdaptiveExtensionClass() -->getExtensionClasses()//为cachedClasses 赋值 -->loadExtensionClasses() -->loadFile -->createAdaptiveExtensionClass()//自动生成和编译一个动态的adpative类,这个类是一个代理类 -->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension() -->compiler.compile(code, classLoader) -->injectExtension()//作用:进入IOC的反转控制模式,实现了动态入注

总结

1、dubbo 设计了一系列缓存,jdk spi 不支持缓存;

2、dubbo 设计了默认初始化的类,jdk spi 不支持;

3、dubbo 动态获取 SPI 对象,jdk spi 需进行 for 循环判断;

4、dubbo 设计了 AOP 功能,XxxxFilterWrapper XxxxListenerWrapper;

5、dubbo 设计了 IOC 功能,wrapperClass.getConstructor(type).newInstance(instance);

猜你喜欢

转载自www.cnblogs.com/kakacbing/p/10519991.html
今日推荐