我正在尝试根据运行时类路径上可用的类来确定创建类的新实例的最佳方法.
例如,我有一个库,需要在多个类中解析JSON响应.该库具有以下界面:
JsonParser.java:
public interface JsonParser {
<T> T fromJson(String json, Class<T> type);
<T> String toJson(T object);
}
Run Code Online (Sandbox Code Playgroud)
这个类有多种实现方式,即GsonJsonParser,JacksonJsonParser,Jackson2JsonParser,目前,图书馆的用户需要"挑"及其实施基础上,他们已经包括在他们的项目,该项目库中使用.例如:
JsonParser parser = new GsonJsonParser();
SomeService service = new SomeService(parser);
Run Code Online (Sandbox Code Playgroud)
我想做的是,动态地选择哪个库在类路径上,并创建适当的实例,以便库的用户不必考虑它(甚至必须知道它的内部实现另一个类解析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");
Run Code Online (Sandbox Code Playgroud)
这是一个合适的解决方案吗?它似乎有点像黑客,并使用异常来控制流程.
有一个更好的方法吗?
And*_*niy 10
基本上你想创建自己的JsonParserFactory.我们可以看到它是如何在Spring Boot框架中实现的:
public static JsonParser getJsonParser() {
if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
return new JacksonJsonParser();
}
if (ClassUtils.isPresent("com.google.gson.Gson", null)) {
return new GsonJsonParser();
}
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
return new YamlJsonParser();
}
return new BasicJsonParser();
}
Run Code Online (Sandbox Code Playgroud)
因此,除了使用该ClassUtils.isPresent方法之外,您的方法几乎与此相同.
如果只实现之一(GsonJsonParser,JacksonJsonParser,Jackson2JsonParser)将出现在运行时,有没有其他选择,那么你不得不使用Class.forName().
虽然你可以更聪明地处理它.例如,您可以将所有类放入a Set<String>然后循环它们.如果其中任何一个抛出异常,你可以继续,而那个没有,你可以做你的操作.
是的,它是一个黑客,你的代码将依赖于库.如果你有可能在你的类路径中包含你的JsonParsers的所有三个实现,并使用逻辑来定义你必须使用哪个实现; 这将是一个更好的方法.
如果无法做到这一点,您可以继续上面的操作.
此外,Class.forName(String name)您可以使用更好的选项,而不是使用plain ,Class.forName(String name, boolean initialize, ClassLoader loader)而不会运行任何静态初始化程序(如果您的类中存在).
哪里initialize = false和loader = [class].getClass().getClassLoader()
| 归档时间: |
|
| 查看次数: |
1443 次 |
| 最近记录: |