【发布时间】:2017-06-08 16:15:22
【问题描述】:
我正致力于创建一个非常简单的类似操作系统的框架(类似于 Android),它基于 JVM 构建,用于教育目的。
大多数情况下,我只是想了解ClassLoaders 以及它们的无限可能性。我已经创建了大部分基础架构,但我质疑是否有更好的方法来处理我所处情况的泛型。
对我的框架运行方式的一点描述:
"App" 我的框架中的实现能够附加扩展,即插件。扩展系统通过要求扩展实现App 代码知道的接口来工作,但App 代码根本不知道扩展,它只知道接口。
这就是我使用ClassLoaders 的地方。我使用URLClassLoader 以递归方式加载$ApplicationRoot/ext 目录中的所有.class 文件并测试是否从加载的接口isAssignable(类).
这一切都很好而且很花哨,除非我尝试进一步概括它。我想要做的是拥有可以处理所有这些的 SDK 代码,因此应用程序只需要确保正确的扩展位于正确的文件夹中。
这是我现在的代码:
Set<String> classFiles = new HashSet<>();
gatherAllClassFiles("", classFiles, srcRoot);
gatherAllClassFiles("", classFiles, extRoot);
URLClassLoader ucl = new URLClassLoader(new URL[]{extRoot.toURI().toURL(), srcRoot.toURI().toURL()});
for(String className:classFiles){
Class<?> clazz = ucl.loadClass(className);
for(String extension: extensionInterfaceNames){
Class<?> iface = Class.forName(extension);
if(iface.isAssignableFrom(clazz)){
extensions.putIfAbsent(iface, new ArrayList<>());
extensions.get(iface).add(iface.cast(clazz.newInstance()));
}
}
}
extensions 声明如下:
private Map<Class<?>, List<?>> extensions;
我知道泛型的这种实现一点也不理想,事实上,在目前的状态下,它不会编译,但我真的很想远离使用List<Object>。
我真正想做的是这样的:
private Map<Class<?>, List<iface>> extensions;
鉴于iface 是保存类信息的Class 变量的名称,而不是实际的类型,这将不起作用。
我的直觉是,我将不得不接受它并使用List<Object> 并且不安全地将其丢弃,但我希望其他人可能有更好的建议。
【问题讨论】:
-
App知道扩展超级接口,所以每个扩展都应该实现那个接口,对吧?或者您是否试图将类加载例程推广到任意种类的类文件? -
@Radiodef 正是后者
-
@Radiodef 每个
App都有自己的prop.xml文件,该文件具有extension标记,用于拼出每种扩展类型的接口名称。extensionInterfaceNamesList是从 xml 输入加载器的数据。这个想法是,一旦App完全加载,它就可以根据接口名称检索扩展列表。假设App是一个具有一些内置功能的计算器,但也许在线商店可以提供附加功能的下载链接。可能有一个Calculation接口,所有这些附加组件都实现了 -
Calculation接口将特定于App -
关闭选民和反对选民是否愿意分享他们决定背后的理由?还是您真的不关心网站的完整性,只是盲目地点击反对票和关闭投票按钮?
标签: java generics interface casting classloader