ServiceLoader加载插件返回的Iterable对象是否有序?
ServiceLoader返回的Iterable是否有序?
直接给结论:ServiceLoader.load()返回的Iterable默认是无序的,哪怕你的JmjrstPlugin实现了Comparable接口,ServiceLoader也不会自动帮你对实例进行排序。
为什么默认无序?
ServiceLoader的加载顺序由两个不稳定的因素决定:
- 类加载器搜索包含
META-INF/services/[你的接口全类名]文件的jar包、资源的顺序 - 每个
META-INF/services配置文件中,类名的书写顺序
这两个因素都不可靠——比如不同环境下jar包的加载顺序可能变化,或者插件配置文件的存放位置不同,都会导致最终的实例顺序不可预测。
如何得到有序的插件列表?
既然你的JmjrstPlugin已经实现了Comparable,只需要手动把ServiceLoader返回的Iterable转换成集合,再调用排序方法即可。给你两个常见的实现方式:
方式1:用ArrayList和Collections.sort
public static List<JmjrstPlugin> getOrderedPlugins() { List<JmjrstPlugin> pluginList = new ArrayList<>(); ServiceLoader.load(JmjrstPlugin.class).forEach(pluginList::add); Collections.sort(pluginList); // 依赖你实现的compareTo规则排序 return pluginList; }
方式2:用Stream API
import java.util.stream.Collectors; public static List<JmjrstPlugin> getOrderedPlugins() { return ServiceLoader.load(JmjrstPlugin.class) .stream() .map(ServiceLoader.Provider::get) .sorted() // 自动使用Comparable的排序规则 .collect(Collectors.toList()); }
这样就能保证返回的插件列表严格按照你在compareTo中定义的规则排序,不受加载顺序的影响。
内容的提问来源于stack exchange,提问作者T. Grumser
相关产品推荐
相关产品推荐

