9

我想查看 jar 中的类是否实现了特定的接口。我已经实现了下面的代码,但是它遍历了 jar 文件中的所有类,并在每个类上查找它是否实现了这个特定的接口。

    public static synchronized boolean findClassesInJar(final Class<?> baseInterface, final String jarName){
        final List<String> classesTobeReturned = new ArrayList<String>();
        if (!StringUtils.isBlank(jarName)) {
            //jarName is relative location of jar wrt. 
            final String jarFullPath = File.separator + jarName;
            final ClassLoader classLoader = this.getClassLoader();
            JarInputStream jarFile = null;
            URLClassLoader ucl = null;
            final URL url = new URL("jar:file:" + jarFullPath + "!/");
            ucl = new URLClassLoader(new URL[] { url }, classLoader);
            jarFile = new JarInputStream(new FileInputStream(jarFullPath));
            JarEntry jarEntry;
            while (true) {
                jarEntry = jarFile.getNextJarEntry();
                if (jarEntry == null)
                    break;
                if (jarEntry.getName().endsWith(".class")) {
                    String classname = jarEntry.getName().replaceAll("/", "\\.");
                    classname = classname.substring(0, classname.length() - 6);
                    if (!classname.contains("$")) {
                        try {
                            final Class<?> myLoadedClass = Class.forName(classname, true, ucl);
                            if (baseInterface.isAssignableFrom(myLoadedClass)) {
                                return true;
                            }
                        } catch (final ClassNotFoundException e) {

                        } 
                    }
                }
            }
        return false;
    }

有什么简单的方法可以做到这一点吗?因为如果有一个 jar 有 100 个类文件并且第 100 个类实现了这个接口,通过上面的代码我需要遍历所有 100 个类文件,看看它是否实现了接口。有什么有效的方法吗?

4

5 回答 5

11

Reflections库可以做到这一点:

Reflections reflections = new Reflections(
    ClasspathHelper.forPackage("your.root.package"), new SubTypesScanner());
Set<Class<? extends YourInterface>> implementingTypes =
     reflections.getSubTypesOf(YourInterface.class);
于 2013-05-14T15:02:51.193 回答
3

Spring为此提供了一些帮助代码,ClassPathScanningCandidateComponentProvider但它基本上可以完成您所做的工作。

您可能还想看一下弗洛伊德,它是一个舒适的工具包,可以编写静态分析测试,例如确保某个包中的所有类或实现某个接口的所有类也实现equals()hashCode()

Freud 的好处在于它可以分析 Java源代码和类文件(即源代码和编译后的字节码),它可以查看属性或文本文件,它可以读取 CSS 和 Spring 配置(因此它可以确保所有重要的DAO bean 的方法有@Transactional)。

于 2013-05-14T17:41:12.757 回答
0

任何现代 IDE(eclipse、IntelliJ、...)都应该能够找到特定接口(或类或方法)的用法。

如果您有 jar 文件的源代码,则可以将其作为依赖项添加到您的项目中。或者,您可以简单地解压缩 jar 的内容并在 IDE 中将其作为项目打开,然后找到您感兴趣的接口的用法。

于 2013-05-14T14:59:19.010 回答
0

一般来说,没有简单的方法。甚至没有获取该信息的通用方法。

这里的问题在于 Java 的类加载机制。在实际加载某个类之前,您无法判断它是否实现了接口。如果不尝试加载类,您将无法判断它是否存在(请注意,您甚至无法判断类路径上哪些类可用)。

这里的原因很简单,类加载器不提供任何枚举类功能,原因是类路径可能无限大/深,并且检索该枚举的成本(及时)可能是无限的(想想一个URL 类加载器,可将您连接到大型远程代码存储库)。

所以你的方法已经尽可能好。

于 2013-05-14T15:43:22.587 回答
0

您可以为此使用 IntelliJ。创建一个虚拟项目,并将您的 jars 添加到类路径中。然后打开您的界面,然后单击界面名称左侧的 (I) 图标。不确定 Ecilse,但很确定你也可以这样做。

上课也是如此。

在此处输入图像描述

于 2016-01-03T23:02:59.640 回答