在运行时替换包中的类以解决版本冲突

时间:2014-06-29 16:37:35

标签: java maven dependency-injection classpath

我正在开发一个在运行时加载插件类的平台的插件,这个平台使用旧版本的javax.persistence API(特别是1.0版),而我的插件需要2.1版,因为它使用了hibernate 4.3.5.Final。

我正在寻找一种方法来删除当前包中的所有类' javax.persistence'并在运行时加载我的插件jar中构建的较新的javax.peristence类。我的插件运行的平台构建为一个jar,并且使用shade maven插件在jar中内置了所有依赖项(包括javax.persistence),这对于插件的所有依赖项都是一样的。

那么有可能实现这个目标吗?能够在运行时用较新的版本替换类路径的依赖关系吗? 如果不可能,或者非常困难,我总是可以分叉平台,并更改pom.xml以将javax.peristence类排除在阴影之外......但这不是更可取的......

编辑:另一种选择是在部署之前编写一个小脚本来替换jar中的类文件。至少这样做会使我每次需要更新平台时都不必手动替换类

感谢。

1 个答案:

答案 0 :(得分:1)

如果需要在运行时加载类,可以使用:

URLClassLoader child = new URLClassLoader (myJar.toURL(), this.getClass().getClassLoader());
Class classToLoad = Class.forName ("com.MyClass", true, child);
Method method = classToLoad.getDeclaredMethod ("myMethod");
Object instance = classToLoad.newInstance ();
Object result = method.invoke (instance);

但当然这会引起控制你的罐子的问题,当然还有缺乏安全性。

我完全建议通过maven控制您的依赖项。

顺便说一句,如果你有类冲突,你总是可以使用非常有用的maven目标dependency-tree来查看jar依赖于其他jar。即使您需要深入分析,也可以使用dependency-analyze

有关这些非常有用的目标的更多详细信息,请查看以下链接:

http://maven.apache.org/plugins/maven-dependency-plugin/plugin-info.html

编辑:作为此答案的更新,您可以尝试JCL (java class loader framework)看起来很有趣。它的描述说:

  

JCL是一个可配置,动态且可扩展的自定义类加载器   直接从Jar文件和其他源加载java类。该   动机是创建孤立的类加载器,这很容易   与Spring和Web应用程序等IoC框架集成。

一个例子:

  JarClassLoader jcl = new JarClassLoader();

  //Loading classes from different sources
  jcl.add("myjar.jar");
  jcl.add(new URL("http://myserver.com/myjar.jar"));
  jcl.add(new FileInputStream("myotherjar.jar"));
  jcl.add("myclassfolder/");

  //Recursively load all jar files in the folder/sub-folder(s)
  jcl.add("myjarlib/");

  JclObjectFactory factory = JclObjectFactory.getInstance();

  //Create object of loaded class
  Object obj = factory.create(jcl, "mypack.MyClass");

希望能提供帮助