反思+库java

时间:2013-06-24 11:57:30

标签: java reflection

编辑:这是项目设置:

IDE:Eclipse:

Project1:“服务器”

src:
com/mainpackage/main.java
libs:
commons-x-0.jar
PluginInterface.jar

libs-folder中的所有jar都在buildpath上。

Project2:“PluginInterface”

src:
com/interfaces/plugininterface

Project3:“插件”

src:
com/package/class1.java - (this implements plugininterface)
libs:
library1.jar
PluginInterface.jar

libs-folder中的所有jar都在buildpath上

所以当我导出插件(Project3)时,我得到一个这样的jar(从导出中排除PluginInterface.jar)

com/
com/package/
com/package/class1.class
com/package/class1.java
libs/
libs/library1.jar

library1.jar看起来如下 - 它不是我写的:

com/
com/stuff/
com/stuff/libclass.java
com/stuff/libclass.class

现在我想通过界面在“服务器”中使用class1:

ClassLoader loader=URLClassLoader.newInstance( 
                new URL[]{new URL("file:path/to/plugin.jar")},
                ClassLoader.getSystemClassLoader()
        );

Class<?> pluginclass = Class.forName("com.package.class1", true, loader);
plugininterface ref = (plugininterface)pluginclass.newInstance();

我现在可以使用项目知道的接口调用class1中的方法,因为它们在构建路径中都包含“PluginInterface.jar”。

问题:

“服务器”无法识别“libclass”,因为它既不在路径中,也不从插入library1的plugin.jar中加载类。

如果在服务器上无法导入库,我该如何访问此类?

感谢您的帮助!

编辑:只是为了有人再次遇到这个问题,我会添加ANT文件的构建目标,使其工作:

<target name="build">
     <javac destdir="bin" includeantruntime="false" source="1.7" target="1.7">
        <src path="src"/>
        <classpath refid="Plugin.classpath"/>
     </javac>
    <unzip src="${libs}/library1.jar" dest="bin/">
        <patternset>
            <include name="**/*.class"/>
        </patternset>
</unzip>
    <jar destfile="plugin.jar" basedir="bin"></jar> 
</target>

只需将Library-jar的内容复制到构建目录(在我的情况下为./bin/)。然后甚至不需要将库类提供给类加载器,它在加载类时会找到它们使用它们。

2 个答案:

答案 0 :(得分:11)

标准类加载器不支持嵌套的jar文件。您可以以编程方式提取jar,或编写自己的类加载器,它将按需解压缩嵌套文件。但是,你会逆流而行:这种包装不推荐。相反,建议将嵌套jar分解为其父级。例如,这是Maven依赖插件的作用,以及使用Leiningen发布Clojure应用程序的默认方式。

为了从Eclipse实现您的目标,最好的方法似乎是:

  1. 让Eclipse的Export JAR向导保存它在内部生成的ant构建脚本,以构建您的JAR;

  2. 调整生成的脚本以满足您的特定需求;

  3. 将来不再运行向导,而是蚂蚁脚本。

答案 1 :(得分:0)

正如Marko所提到的,您的标准类加载器不会扫描嵌套的jar和嵌套的jar。但是,如果您愿意使用TrueZip,则无需提取档案或任何内容即可轻松完成此操作。更好的是,您可以在嵌套档案中尽可能深地嵌套档案。所以你的路径看起来像:

/path/to/foo.jar/bar/foo/my.zip/containing/some.tar/com/foo/My.class

如果您觉得使用TrueZip编写自己的类加载器感觉很舒服,这将是一种巧妙的方法。如果没有,那么您必须编写一个实用程序类来解析路径并首先提取存档,然后再将其提供给标准URLClassloader