1

背景

我有一个必须更新的公共库。这个公共库有一个第三方依赖(jgroups),它在新版本中发生了显着变化。通过传递依赖,有时需要更新版本的 jgroups,这会破坏公共库。我需要更新一些类以兼容新版本,同时保持向后兼容性。

问题

JGroups 提供了一个View类,它有一个方法getMembers()。在旧版本 (2.10.0) 中,此方法返回Vector<Address>,而在较新版本 (3.2.7) 中,此方法返回List<Address>. 的任何实现java.util.Collection都对我有用,但问题是我得到了一个NoSuchMethodException. 据我了解,getMembers()找到的方法具有旧的Vector<Address>返回类型(基于公共库中的 JGroups 依赖项),但我正在拖入较新的 JGroups 版本,并且View该类期望List<Address>从该getMembers()方法返回。

堆栈跟踪

在 Eclipse 中启动我的应用程序时出现以下错误。

Caused by: java.lang.NoSuchMethodError: org.jgroups.View.getMembers()Ljava/util/Vector;
    at com.mycompany.commons.messaging.events.impl.distributed.JGroupsEventDistributionProvider$JGroupsEventReceiver.viewAccepted(JGroupsEventDistributionProvider.java:136) ~[classes/:na]
    at org.jgroups.JChannel.invokeCallback(JChannel.java:752) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
    at org.jgroups.JChannel.up(JChannel.java:710) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
    at org.jgroups.stack.ProtocolStack.up(ProtocolStack.java:1020) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
    at org.jgroups.protocols.pbcast.FLUSH.up(FLUSH.java:466) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
 ....

哪里断了

Collection<Address> viewMembers = view.getMembers();

问题

是否可以支持这两个版本,即使它们是不同的实现Collection?我该如何处理这种直到运行时才知道方法返回类型的场景?

笔记:

我试图通过在我的 maven pom.xml 中添加排除项来排除正在引入的旧版本的 JGroups。这没有奏效。

    <dependency>
        <groupId>com.mycompany.commons</groupId>
        <artifactId>mycompany-commons-event-distributed-jgroups</artifactId>
        <!-- Note: JGroups dependency is provided by infinispan -->
        <version>1.0.2-SNAPSHOT</version>
        <type>jar</type>
        <scope>compile</scope>
        <exclusions>
            <exclusion>
                <groupId>org.jgroups</groupId>
                <artifactId>jgroups</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
4

2 回答 2

2

使用反射怎么样?字段 View.members 在 2.10.x 中是一个 Vector,在 3.x 中是一个 Address[] 数组。您可以访问字段 View.members 并 - 根据其类型 - 将所有成员作为地址集合返回。不好,但应该工作..

于 2015-08-29T20:51:44.943 回答
1

如果您在应用程序框架中使用“普通 java”,我认为您通常不走运。

如果不使用诸如 OSGI 之类的模块框架,您只有一个类池,并且加载到类路径中的每个类都会进入该池。这意味着您不能在 JVM 中同时拥有同一个 JAR 或同一个类的多个版本。

此外,您必须支持同一个 JAR 的多个版本,因为您至少有两段代码分别针对不同的版本编译:一个期望返回值 ,Vector另一个期望返回值List,所以即使您可以将不需要的代码与构建环境,针对它构建的代码将不会链接到正确的二进制文件,您将继续获得您看到的运行时异常。

不幸的是,您提到这是一个“库”,而不仅仅是一个应用程序,这可能会使应用解决方案变得更加困难。在我的脑海中,我看到这些选项可以让您继续前进,其中没有一个是微不足道的,有些可能是不可能的:

  1. 根据需要降级您的代码,以便在所有依赖链中只有一个版本的 jgroup
  2. 重新架构您的应用程序以使用 OSGI 或支持同一库的多个版本的类似框架,因此依赖链可能会出现分歧
  3. 重新架构您的应用程序并将其分割成多个,每个都在自己的 JVM 中运行,通过套接字或任何其他方式进行通信

例如,我们使用第三个选项来拆分应用程序的一小部分,因此它可能依赖于许可对我们整个代码库不友好的库,但该部分可以与库一起获得许可。

我也不确定 Java 9 模块系统会如何处理这个问题,但它可能在运行时同时支持同一模块的多个版本。如果您可以选择使用该测试版或进行调查,那可能值得您付出努力。但是,您提到重点是向后兼容性,因此这也可能不是一个可行的选择。

于 2015-08-27T02:47:58.763 回答