接口
@SPI
public interface MyTestRegistry {
/**
* 注册服务
*/
@Adaptive
String register(URL url);
}
两个实现
@Activate(group = {"GROUP_A", "GROUP_B"}, order = 999)
public class EtcdRegistry implements MyTestRegistry {
@Override
public String register(URL url) {
return "Etcd register already! ";
}
}
@Activate(group = {"GROUP_B"})
public class ZookeeperRegistry implements MyTestRegistry {
@Override
public String register(URL url) {
return "Zookeeper register already! ";
}
}
配置
etcd=com..xxx.xxx.xxx.EtcdRegistry
zookeeper=com.xxx.xxx.xxx.ZookeeperRegistry
测试函数
public class SpiTest {
public static void main(String[] args) {
URL url = URL.valueOf("test://localhost/test")
.addParameter("my.test.registry", "zookeeper");
MyTestRegistry registry = ExtensionLoader
.getExtensionLoader(MyTestRegistry.class)
.getExtension("etcd");
System.out.println("=================");
System.out.println(registry.register(url));
System.out.println("=================");
registry = ExtensionLoader
.getExtensionLoader(MyTestRegistry.class)
.getAdaptiveExtension();
registry.register(url);
System.out.println(registry.register(url));
System.out.println("=================");
ExtensionLoader
.getExtensionLoader(MyTestRegistry.class)
.getActivateExtension(url, new String[]{}, "GROUP_B")
.forEach(p -> System.out.println(p.register(url)));
System.out.println("=================");
}
}
输出
=================
Etcd register already!
=================
Zookeeper register already!
=================
Zookeeper register already!
Etcd register already!
=================
总结
@SPI 标注是一个扩展点,各种实现配置在配置文件里(key是实现名字,类似spring里的bean name,value是实现类)
@Adaptive 是自适应注解,根据使用时url里的参数,动态寻找实现类
@Activate 是激活注解,可以激活一串实现,常用于filter
注解参数说明
@SPI 的 value (默认使用的extension,可填配置里的etcd或zookeeper)
@Adaptive 的 value (调用时,动态匹配url里key的名字,不填为类的驼峰转换xxx.xx.xx)
@Activate 的 group (把所有实现,进行分组,激活时,激活整个组)
@Activate 的 value (类似@Adaptive的value)
@Activate 的 order (激活时排序)