概述
Spi测试的基础环境
一个Shape的接口,有一个draw方法
一个Circle类和Rect类实现Shape,重写draw方法
代码如下:
// 接口:形状
public interface Shape {
void draw();
}
// 圆类,实现形状接口
public class Circle implements Shape {
public void draw() {
System.out.println("画一个圆");
}
}
// 矩形类,实现形状接口
public class Rect implements Shape {
public void draw() {
System.out.println("画一个矩形");
}
}
Java的Spi
- 在resources下创建一个META-INF/services/文件夹
- 创建以Shape接口的全限定名为文件名
- 在文件里写需要加载的子类
- 编写测试类,通过ServiceLoader类来获取Shape下的在配置文件里配置的子类。
public class JavaSpiTest {
public static void main(String[] args) {
Shape shape;
ServiceLoader<Shape> serviceLoader = ServiceLoader.load(Shape.class);
Iterator<Shape> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
shape = iterator.next();
shape.draw();
}
}
}
- 结果
- 总结,JavaSpi的机制会加载配置文件里所有的类,但是如果你只需要几个类,会造成空间的浪费。
Dubbo的Spi
dubbo的spi对java spi的弊端做了改进。
相比于java spi的全量加载,dubbo spi 可以做到按需加载。
- 在resources下创建一个META-INF/dubbo/文件夹(注意:dubbo可以加载三个文件夹,这里以dubbo文件夹测试)
- 在dubbo文件夹下创建以接口全类名为名的文件,在里面创建以key = val的形式编写。
- 在接口上加@Spi的注解,
@SPI("circle")
表示指定默认的加载项
@SPI("circle")
public interface Shape {
void draw();
}
- 测试类
public class DubboSpiTest {
public static void main(String[] args) {
ExtensionLoader<Shape> extensionLoader = ExtensionLoader.getExtensionLoader(Shape.class);
//根据key去获取对应的类
Shape rect = extensionLoader.getExtension("rect");
rect.draw();
Shape circle = extensionLoader.getExtension("circle");
circle.draw();
//默认类,@SPI("circle")根据这个值获取
Shape defaultExtension = extensionLoader.getDefaultExtension();
defaultExtension.draw();
}
}
输出结果
@Adaptive注解
注解加在类上
@Adaptive
public class Circle implements Shape {
public void draw() {
System.out.println("画一个圆");
}
}
@Test
void test2() {
ExtensionLoader<Shape> extensionLoader = ExtensionLoader.getExtensionLoader(Shape.class);
Shape shape3 = extensionLoader.getAdaptiveExtension();
shape3.draw();
}
注解加在接口的方法上
注解加在接口的方法上,会动态生成Shape$Adaptive
, 然后解析传入的URL参数,根据key值,调用对应的类的方法。
@SPI("circle")
public interface Shape {
void draw();
// 去解析url,从里面提取key=name的value值 对应的类
@Adaptive("name")
void draw(URL url);
}
public class Circle implements Shape {
public void draw() {
System.out.println("画一个圆");
}
public void draw(URL url) {
System.out.println("画一个圆"+url);
}
}
public class Rect implements Shape {
public void draw() {
System.out.println("画一个矩形");
}
public void draw(URL url) {
System.out.println("画一个矩形"+url);
}
}
测试类
//Adaptive 在方法上
@Test
void test3() {
ExtensionLoader<Shape> extensionLoader = ExtensionLoader.getExtensionLoader(Shape.class);
Shape shape = extensionLoader.getAdaptiveExtension();
// 设置name = circle ,Adaptive去获取对应circle的类,并调用
URL url = URL.valueOf("dubbo://localhost/server?name=circle");
shape.draw(url);
}
断点查看shape的类型:
运行结果:
Spi应用
除了在Dubbo源码中大量运用spi之外,还能在其他应用中看到它的使用。
比如spring的web模块。
- 当web容器启动后,提供第三方应用一些初始化的操作。servlet规范中通过ServletContainerInitializer就可以实现此功能。
- spring中实现了ServletContainerInitializer这个类,并通过spi引导和加载自定义实现类,重写onStartup方法
- 并结合
@HandlesTypes(WebApplicationInitializer.class)
注解,在onStartup方法里注入该对象。
最后
以上就是高挑帽子为你收集整理的Java spi和Dubbo spi的对比以及应用的全部内容,希望文章能够帮你解决Java spi和Dubbo spi的对比以及应用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复