背景
我有一个公共图书馆,我必须更新。此公共库具有第三方依赖项(jgroups),在较新版本中已显着更改。通过传递依赖,有时需要更新版本的jgroups,这会破坏公共库。我需要更新一些类以与新版本兼容,同时保持向后兼容性。
问题
JGroups提供了一个View
类,其方法为getMembers()
。在旧版本(2.10.0)中,此方法返回Vector<Address>
,在较新版本(3.2.7)中,返回List<Address>
。 java.util.Collection
的任何实现都适用于我,但问题是我得到NoSuchMethodException
。据我了解,找到的getMembers()
方法具有遗留Vector<Address>
返回类型(基于公共库中的JGroups依赖关系),但是我拖入了一个较新的JGroups版本而{{1} } class期望从View
方法返回List<Address>
。
堆栈跟踪
在Eclipse中启动我的应用程序时出现以下错误。
getMembers()
它破裂的地方
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();
的不同实现?如何处理这种情况,直到运行时我才知道方法返回类型?
注意:
我试图通过在我的maven pom中添加排除来排除旧版本的JGroups。这没效果。
Collection
答案 0 :(得分:1)
如果你正在使用&#34;普通的java&#34;对于应用程序框架,我认为你通常都不走运。
如果不使用某种类型的模块框架(如OSGI),您只有一个类池,并且加载到类路径中的每个类都会进入该池。这意味着您不能同时在JVM中拥有相同JAR的多个版本或同一个类。
此外,您必须支持同一JAR的多个版本,因为您针对不同版本至少编译了两个代码:一个期望Vector
的返回值和另一个{{1}因此,即使您可以将不需要的代码与构建环境隔离开来,针对它构建的代码也不会链接到正确的二进制文件,您将继续获得您看到的运行时异常。
不幸的是,你提到这是一个&#34;库&#34;而不仅仅是一个应用程序,这可能使应用解决方案更加困难。在我的脑海中,我看到了这些选择让你向前迈进,没有一个是微不足道的,有些可能是不可能的:
例如,我们使用了第三个选项来拆分应用程序的一小部分,因此它可能依赖于具有对我们整个代码库不友好的许可证的库,但该部分可以与库一起许可。
我也不确定Java 9模块系统如何使用它,但它可能同时支持运行时中同一模块的多个版本。如果您选择使用该测试版或进行调查,那么这可能值得您付出努力。但是,您提到的重点是向后兼容性,因此这可能也不是一个可行的选择。
答案 1 :(得分:1)
使用反射怎么样? Field View.members是2.10.x中的Vector和3.x中的Address []数组。您可以访问字段View.members,并根据其类型将所有成员作为地址集合返回。不好,但应该工作..