我正在研究一个具有大量外部JAR依赖关系的现有应用程序。我需要增强它以与具有API的第三方应用程序集成。可悲的是,API并没有得到很好的控制,并且还附带了大量自己的依赖项,其中一些依赖于我的。
我相信我应该使用类加载器来解决这个问题,但我很难看到如何正确地构造它们。
为了简单起见,假设我们的myapp.jar具有hibernate3.jar依赖性,而vendor-api.jar具有hibernate2.jar依赖性(并假设它们不兼容)。
我的新代码将驻留在myapp.jar库中(尽管如果这会有帮助,它可能在一个单独的jar中)。由于供应商API的工作方式,我的新代码需要从vendor-api.jar库扩展一个类。
如何以这样的方式构造类加载器:vendor-api.jar中的任何内容只访问自己的依赖项,而我身边的任何东西只访问myapp.jar和依赖项?
谢谢,乔恩
答案 0 :(得分:1)
我自己并没有尝试过这种方法,但是从内存中来看,每个冲突类需要在一个兄弟级的类加载器中,并且两者之间的任何通信都需要通过一个共同的祖先。但是,祖先不能(AFAIK)“直接”引用其子类中的类,并且必须通过反射API访问它们。
沿着这些方向的东西应该起作用(干编码)YMMV。评论和错误发现欢迎。
class Orchestrator {
URL[] otherAppClasspath = new URL[] { new URL("file:///vendor-api.jar"),
new URL("file:///hibernate2.jar"),
new URL("file:///code-extending-vendor-api.jar" };
URLClassLoader otherAppLoader = new URLClassLoader(otherAppClasspath);
URL[] yourAppClasspath = new URL[] { new URL("file:///myapp.jar"),
new URL("file:///hibernate3.jar") };
URLClassLoader yourAppLoader = new URLClassLoader(yourAppClasspath);
public void start() {
Method yourAppEntryPoint = yourAppLoader.findClass("com/company/Main").getMethod("start", new Class[] { Orchestrator.class } );
yourAppEntryPoint.invoke(null, new Object[] { this });
}
public static void main(String[] args) {
new Orchestrator().start();
}
// define some abstracted API here that can be called from your app
// and calls down into classes in the other app
public String getSomeResultFromOtherApp(int someArgument) {
Method otherAppAPI = otherAppLoader.findClass("com/company/ExtendingAPIClass").getMethod("getSomeResult", new Class[] { Integer.class });
return (String)otherAppAPI.invoke(null, new Object[] { someArgument });
}
}
答案 1 :(得分:0)
@ fd的答案提供了一个应该有效的技术机制 - 给予或者采取一些拼写错误,异常处理等。
但是,我认为最好不要尝试这样做...除非您对第三方API的依赖仅限于极少数类的极少数方法。您依赖的每个类都必须动态加载,并且必须以反射方式查找和调用每个方法。太多,你的代码库将受到影响。
如果我是你,我会尝试以其他方式解决依赖问题:
根据你的说法,这可能很难。
答案 2 :(得分:0)
使用OSGi可以长期帮助您。以下是我正在尝试的实现 - http://felix.apache.org