【发布时间】:2016-05-23 00:38:33
【问题描述】:
我正在尝试根据运行时类路径中可用的类来确定创建类的新实例的最佳方法。
例如,我有一个库,它需要在多个类中解析 JSON 响应。该库有如下接口:
JsonParser.java:
public interface JsonParser {
<T> T fromJson(String json, Class<T> type);
<T> String toJson(T object);
}
这个类有多个实现,即GsonJsonParser、JacksonJsonParser、Jackson2JsonParser,目前,库的用户需要根据他们所包含的库来“选择”他们要使用的实现他们的项目。例如:
JsonParser parser = new GsonJsonParser();
SomeService service = new SomeService(parser);
我想做的是动态选择类路径上的库,并创建适当的实例,这样库的用户就不必考虑它(甚至不必知道另一个类的内部实现解析 JSON)。
我正在考虑类似于以下内容:
try {
Class.forName("com.google.gson.Gson");
return new GsonJsonParser();
} catch (ClassNotFoundException e) {
// Gson isn't on classpath, try next implementation
}
try {
Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
return new Jackson2JsonParser();
} catch (ClassNotFoundException e) {
// Jackson 2 was not found, try next implementation
}
// repeated for all implementations
throw new IllegalStateException("You must include either Gson or Jackson on your classpath to utilize this library");
这是一个合适的解决方案吗?它看起来有点像 hack,并且使用异常来控制流程。
有没有更好的方法来做到这一点?
【问题讨论】:
-
我同意,这是一个 hack。选择一个 JSON 解析器依赖项并使用它?您的方法也可能意外地不确定;根据 JAR(可能还有类路径中 JAR 的顺序),程序行为可能会发生变化。
-
@ElliottFrisch 我想这样做,但目前将使用它的应用程序具有这些解析器中的任何一个,我试图避免让第二个成为依赖项,如果它是不同于我决定打包的那个(或相同的库,不同的版本)。
-
-
@Andremoniy 是的,Spring 也这样做;它仍然是一个hack。我什至承认这似乎是一个聪明的黑客攻击。但是,如果 Java 9+ 添加了一个内置的 JSON 解析器,那么它追溯就变成了?
-
@Casey 当类路径上的类丢失时,如何编译实现?
标签: java