无法在Java应用程序中使用interfaced插件类支持暴露自定义类,Jar在Jar中

时间:2017-01-10 17:30:52

标签: java spring classpath

我有一个使用websockets进行通信的服务器/客户端设置,它们都是Spring Boot应用程序,用于通信的消息类是在一个单独的项目中进行的,并且#34; CommonClasses"。

Server和Client项目都在其构建路径上具有CommonClasses项目,这使它们可以访问共享消息类型。

客户端将从服务器收到一条消息,并在响应之前对其进行操作。 到目前为止,客户端可以执行的功能数量有限,但目的是向客户开放这些功能以设计自己的实现。为此,有一个必须实例化的applier接口,我只需将Client添加到新项目的类路径中,放入我的新实现并使用客户端中的classpath加载器来加载这个新的jar并调用新方法。

如果我有一个vanilla方法,但是当我尝试实现之前传递消息的实际接口时,这是有效的,如CommonClasses中所详述。

如果我解压缩客户端jar文件并将生成的CommonClasses jar文件添加到我的类路径中,我可以看到这些类,但是当我这样做并尝试将实例化对象强制转换为我的接口类型时,我得到了一个java.lang.ClassCastException。

我已经对堆栈溢出进行了研究,我得出的结论是,虽然客户端接口和新项目中引用的接口具有相同的签名和项目,但它们被视为不同的对象。因为我必须从客户端jar中提取CommonClasses jar。

我有什么选择? 我知道我可以创建一个新的接口,只使用简单的java类型并转换所有内容,但这将是昂贵的,并希望尽可能避免这种情况。 可以更改现有项目构建过程,但如果可能,应尽量避免。

这就是我到目前为止:

    URL[] classLoaderUrls = new URL[]{new URL("file:C:\\customApplier.jar")};
    // Create a new URLClassLoader
    URLClassLoader urlClassLoader = new URLClassLoader(classLoaderUrls);
    // Load the target class
    Class<?> beanClass = urlClassLoader.loadClass("com.test.Applier");
    // Create a new instance from the loaded class
    Constructor<?> constructor = beanClass.getConstructor();
    ApplierIn ob = (ApplierIn)constructor.newInstance();

尝试强制转换为(ApplierIn)时抛出异常。谢谢你的建议!

1 个答案:

答案 0 :(得分:2)

感谢@ Klaus-Groenbaek能够识别问题,这确实是一个错误的类加载器。所以我把它改成了:

    private static void addCustomJar(URL fileUrl) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(ApplierIn.class.getClassLoader(), new Object[]{fileUrl});
}

为了将新的jar文件加载到我的应用程序中。在那之后,事实证明罐子里的解包jar不是问题!