我正在开发一个在运行时加载插件类的平台的插件,这个平台使用旧版本的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中的类文件。至少这样做会使我每次需要更新平台时都不必手动替换类
感谢。
答案 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");
希望能提供帮助