我想找出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;
}
有没有简单的方法可以做到这一点?因为如果有一个包含100个类文件且第100个类的jar已实现此接口,通过上面的代码我需要迭代所有100个类文件并查找它是否已实现接口。有没有有效的方法呢?
答案 0 :(得分:10)
Reflections库可以做到这一点:
Reflections reflections = new Reflections(
ClasspathHelper.forPackage("your.root.package"), new SubTypesScanner());
Set<Class<? extends YourInterface>> implementingTypes =
reflections.getSubTypesOf(YourInterface.class);
答案 1 :(得分:3)
Spring在ClassPathScanningCandidateComponentProvider
中有一些帮助代码,但它基本上就是你所做的。
您可能还想查看Freud这是一个编写静态分析测试的舒适工具包,例如确保某个包中的所有类或实现某个接口的所有类都实现equals()
和{ {1}}
关于弗洛伊德的好处是它可以分析Java 源代码和类文件(即源代码和编译的字节代码),它可以查看属性或文本文件,它可以读取CSS和Spring配置(因此它可以确保DAO bean的所有重要方法都有hashCode()
)。
答案 2 :(得分:0)
任何现代IDE(eclipse,IntelliJ,...)都应该能够找到特定接口(或类或方法)的用法。
如果您拥有jar文件的源代码,则可以将其作为依赖项添加到项目中。或者,您只需解压缩jar的内容并将其作为IDE中的项目打开,并找到您感兴趣的界面的用法。
答案 3 :(得分:0)
一般来说,没有简单的方法。甚至没有获得该信息的通用方法。
这里的问题在于Java的类加载机制。在实际加载接口之前,您无法判断类是否实现了接口。而且你无法判断一个类是否存在而没有尝试加载它(请注意,你甚至无法分辨类路径上哪些类可用。)
这里的原因很简单,类加载器不提供任何枚举类功能,原因是类路径可能无限大/深,并且检索该枚举的成本(及时)可能是无限的(想一个将您连接到大型远程代码存储库的URL类加载器。)
所以你的方法已经尽可能好了。
答案 4 :(得分:0)