检测使用的是哪个 Guava 版本?

Detect which Guava version is used?

我有一个使用旧 Cassandra 驱动程序库的项目,它依赖于版本 20 中已删除的 Guava 已弃用的功能。我正在考虑添加一个测试,当有人不小心将 Guava 的版本从19 到 20。

如何以编程方式找出使用的 Guava 版本?

我没有找到访问该版本的简单方法,但这里有一个适合我的解决方案:

@Test(expected = ClassNotFoundException.class)
public void mustNotUpgradeToGuava20_asItIsIncompatibleWithCassandra() throws ClassNotFoundException {
    Class.forName("com.google.common.graph.Graph");
}

这个测试在 Guava 19 上通过,在 Guava 20 上会失败。Graph class 只是我在发行说明中发现的第一个添加的 classes .

您可以从 guava.jar 中 META-INF/ 下的文件中获取版本字符串。在运行时,你需要使用适当的 ClassLoader 实例来加载你想要的 META-INF/ 文件。您可以使用 Guava 的 Resources 实用程序 class 直接加载具有唯一名称的资源,或者您可以使用 $someGuavaClassName.class.getClassLoader().getResources(String) 在多个 jar 文件中循环访问具有相同名称的资源。如果你选择后者,那么你将需要使用 someGuavaClassName ,它存在于你正在测试的版本中。 Resources 本身从 1.0 开始就在 Guava 中,我不怀疑它很快就会去任何地方,所以应该是安全的 class 使用。

我在 Guava 20.0 和 12.0 上测试了以下内容,它对两者都有效。我怀疑它适用于所有相对较新版本的 Guava:

public class GuavaVersionFetcher {
    public static void main(String... args) throws IOException {
        System.out.println(determineGuavaMavenVersion());
        System.out.println(determineGuavaManifestVersion());
    }

    public static String determineGuavaMavenVersion() throws IOException {
        String resourceName = "META-INF/maven/com.google.guava/guava/pom.properties";
        Properties properties = new Properties();
        try (InputStream inputStream = Resources.getResource(resourceName).openStream()) {
            properties.load(inputStream);
        }
        return properties.getProperty("version");
    }

    public static String determineGuavaManifestVersion() throws IOException {
        Enumeration<URL> resources = Resources.class.getClassLoader()
                .getResources("META-INF/MANIFEST.MF");
        while (resources.hasMoreElements()) {
            Manifest manifest;
            try (InputStream inputStream = resources.nextElement().openStream()) {
                manifest = new Manifest(inputStream);
            }
            Attributes mainAttributes = manifest.getMainAttributes();
            String symbolicName = mainAttributes.getValue("Bundle-SymbolicName");
            if ("com.google.guava".equals(symbolicName)) {
                return mainAttributes.getValue("Bundle-Version");
            }
        }
        return null;
    }
}

示例输出:

20.0
20.0.0

注意:如果 Guava 团队不再使用 Maven,第一种方法可能不再有效,所以我建议使用 manifest 方法。