这是我遇到的问题。有一个运行在Java1.3上的大型遗留应用程序,它使用外部API,比如MyAPI v1.0。MyAPI 1.0的确切实现位于应用程序使用的类路径中的某个位置。还有一种机制,允许应用程序使用外部代码(某种插件机制)。现在我有了另一个java库(MyLib.jar),它使用MyAPI v2.0 (它不是100%向后兼容v1.0),我必须使用这个插件机制从原来的应用程序中使用它。所以我不得不让两个(不相容!)相同API的版本一起工作。具体来说,我想在从MyAPI类调用MyLib.jar类时使用MyAPI v2.0,在所有其他情况下使用MyAPI 1.0。
MyAPI 1.0位于类路径中,因此默认情况下将使用它,没关系。我可以创建自己版本的类加载器,从MyAPI 2.0加载类-没问题。但我该怎么把这一切结合起来呢?问题:
发布于 2009-02-05 12:48:56
让我们从回答第二个问题开始:当从某个类引用到另一个类时,它将由加载原始类的同一个类加载器加载(当然,除非类加载器没有成功地找到类,然后将委托给它的父类加载器)。
话虽如此,为什么您的整个MyLib.jar不通过自定义类加载器加载,然后它可以以常规方式引用新版本的API。否则,您将遇到问题,因为您必须始终使用对象类型和反射。
发布于 2009-02-05 12:41:32
您需要小心使用类加载器。如果您按照您的建议进行操作,那么即使在使用类加载器进行MyAPI 2.0时,您也几乎总是会得到MyAPI 1.0。其原因是如何使用类加载器加载类。类总是先从父类加载器加载。
“ClassLoader类使用委托模型搜索类和资源。ClassLoader的每个实例都有一个相关联的父类加载器。当请求查找类或资源时,ClassLoader实例将把对类或资源的搜索委托给其父类加载器,然后再试图查找类或资源本身。虚拟机的内置类加载器(称为”引导类加载器“)本身没有父类,但可能充当ClassLoader实例的父类。
要正确地提供两个API之间的隔离,您需要两个类加载器(或者除了主要应用程序一个之外,还有两个)。
Parent - System classloader
|- Classloader1 - Used to load MyAPI 1.0
|- Classloader2 - Used to load MyAPI 2.0现在请回答你的问题。您可能要做的是将使用API的大部分逻辑移到类加载器中。除了MyAPI 1.0/2.0之外,您还应该加载应用程序中使用这些部分的部分。然后,父应用程序只需调用一个使用API的方法。通过这种方式,您只需进行一次反射调用就可以启动应用程序,而应用程序中的所有内容都只使用标准引用。
发布于 2009-02-05 12:43:07
您可以在没有反射的情况下使用花哨的ClassLoader来完成这一任务。
基本上,类加载程序必须说“如果加载类来自此jar,则从类路径B加载,否则使用主ClassLoader”。
这比这要复杂一些,但是如果你从这个想法开始,你就会解决的。
https://stackoverflow.com/questions/515702
复制相似问题