dubbo SPI机制

框架设计的有弹性扩展性好会给使用者带来很大的方便,如果业务有新的变化只要使用新的实现去替换之前的实现,且框架如何去加载实现我们也不用太关注,显然这对我们开发者来说是非常友好的。java里的SPI是这个思想,dubbo里的SPI同样是这个思想,关于java里的spi因为会一次性将扩展点逻辑都执行而显得不够灵活,所以这里不再展开(可以参考[java spi](https://www.cnblogs.com/softlin/p/4321955.html)),这里重点说下dubbo里的SPI。

使用方式: 1,在META-INF/services目录下根据接口的全路径名创建一个文件,文件内容为key=value的形式 2,ExtensionLoader.getExtensionLoader(xxx.class).getExtension("key")这样就可以获取到我们自定义的实现了。

下面我们对ExtensionLoader.getExtensionLoader(xxx.class).getExtension(name)这行代码展开下。

`public static ExtensionLoader getExtensionLoader(Class type) {

if (type == null)
throw new IllegalArgumentException("Extension type == null");
//判断给定type是否为接口
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
}
//判断给定接口上是否有SPI注解
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type(" + type +
") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
}
//先从map里获取ExtensionLoader,如果没有进行创建
ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
}
return loader;
}`
这全方法主要是获取ExtensionLoader:
1,对给定的type进行判断,一是判断是否是接口类型;二是判断接口上是否有SPI注解
2,根据给定的type先从Map获取对应的ExtensionLoader,要是没有进行创建。

接下来我们再看看getExtension(name)方法:
`public T getExtension(String name) {

if (name == null || name.length() == 0)
throw new IllegalArgumentException("Extension name == null");
if ("true".equals(name)) {
return getDefaultExtension();
}
//先获取包装类Holder
Holder

posted @ 2022-01-01 18:40  weilu  阅读(62)  评论(0)    收藏  举报