这个问题已经在这里有一个答案:
- 你可以在使用反射包中的所有类? 23个回答
有没有一种方法来遍历在类路径中的所有类?
我想就实现某个接口部分班级一些反射检查,但我想这样做完全动态的,没有任何输入哪个班检查,只是浏览类路径。
这个问题已经在这里有一个答案:
有没有一种方法来遍历在类路径中的所有类?
我想就实现某个接口部分班级一些反射检查,但我想这样做完全动态的,没有任何输入哪个班检查,只是浏览类路径。
该思考图书馆可以帮助解决这个问题。 正如其他人所指出的,它不是完全有可能在所有的类加载的情况,但如果你所有的罐子和文件,这将做到这可靠。
你不能做到这一点优雅。
基本上一个类加载器可以要求加载特定的类名,但不能要求所有它可以加载类。 (在一些加载类通过网络的情况下,它可能不这样做是可行的 - 你不能可靠地询问Web服务器来告诉你一个特定目录下的所有文件。)
如果你的类路径中仅使用文件系统的交易,你可以找到痛苦在扩展目录中的所有jar文件,递归下降正常类路径的目录,并期待所有明确指定的jar文件里面-但它会非常棘手,可能脆弱得。
我已经解决了这个问题一个类加载器。 我需要反思编写代码来检查JUnit测试和被忽略的测试报告。
/**
* Attempts to list all the classes in the specified package as determined
* by the context class loader
*
* @param pckgname
* the package name to search
* @return a list of classes that exist within that package
* @throws ClassNotFoundException
* if something went wrong
*/
private static List<Class> getClassesForPackage(String pckgname) throws ClassNotFoundException {
// This will hold a list of directories matching the pckgname. There may be more than one if a package is split over multiple jars/paths
ArrayList<File> directories = new ArrayList<File>();
try {
ClassLoader cld = Thread.currentThread().getContextClassLoader();
if (cld == null) {
throw new ClassNotFoundException("Can't get class loader.");
}
String path = pckgname.replace('.', '/');
// Ask for all resources for the path
Enumeration<URL> resources = cld.getResources(path);
while (resources.hasMoreElements()) {
directories.add(new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8")));
}
} catch (NullPointerException x) {
throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Null pointer exception)");
} catch (UnsupportedEncodingException encex) {
throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Unsupported encoding)");
} catch (IOException ioex) {
throw new ClassNotFoundException("IOException was thrown when trying to get all resources for " + pckgname);
}
ArrayList<Class> classes = new ArrayList<Class>();
// For every directory identified capture all the .class files
for (File directory : directories) {
if (directory.exists()) {
// Get the list of the files contained in the package
String[] files = directory.list();
for (String file : files) {
// we are only interested in .class files
if (file.endsWith(".class")) {
// removes the .class extension
try
{
classes.add(Class.forName(pckgname + '.' + file.substring(0, file.length() - 6)));
}
catch (NoClassDefFoundError e)
{
// do nothing. this class hasn't been found by the loader, and we don't care.
}
}
}
} else {
throw new ClassNotFoundException(pckgname + " (" + directory.getPath() + ") does not appear to be a valid package");
}
}
return classes;
}
我根据我对解决这个线程的代码 :
我认为你必须手动检查它:
String classpath = System.getProperty("java.class.path");
String[] locations = classpath.split(System.getProperty("path.separator"));
// inspect all jar's and class files in these locations, which is a pain in the b%tt
或者使用一些第三方库,做这个(我不知道有什么)。
我不知道这是否图书馆的,但也有对自己的目的做这个开源项目。 例如, 春天可以遍历类在类路径中寻找那些有一定的注解。 你可以看看他们是如何做到这一点得到一些想法。 我会用在org.springframework.context.annotation包中的类如ClassPathScanningCandidateComponentProvider和CommonAnnotationBeanPostProcessor会开始。
如果你在项目中使用弹簧背景:在这里工作的例子列举所有类型与所需的注释:
/**
* Lists all types in the given package (recursive) which are annotated by the given annotation.
* <p>
* All types which match the criteria are returned, no further checks (interface, abstract, embedded, etc.
* are performed.
* <p>
*
* @param aAnnotation
* the desired annotation type
* @param aRoot
* the package name where to start the search.
* @return a list of found types
*/
private Collection<? extends Class<?>> findCandidatesByAnnotation( Class<? extends Annotation> aAnnotation,
String aRoot )
{
List<Class<?>> result = new ArrayList<Class<?>>();
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider( false )
{
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition)
{
return true;
}
};
scanner.addIncludeFilter( new AnnotationTypeFilter( aAnnotation ) );
Set<BeanDefinition> canditates = scanner.findCandidateComponents( aRoot );
for ( BeanDefinition beanDefinition : canditates )
{
try
{
String classname = beanDefinition.getBeanClassName();
Class<?> clazz = Class.forName( classname );
result.add( clazz );
}
catch ( ClassNotFoundException t )
{
myLog.error( "Springs type scanner returns a class name whose class cannot be evaluated!!!", t );
}
}
return result;
}
此代码是下的java 8抵抗弹簧上下文4.1.1.RELEASE测试。
你不能没有一个定制的ClassLoader。
考虑例如约在那里你从远程服务器甚至不提供目录列表加载类的情况。 你怎么可能遍历所有的课吗?
类加载器接口没有提供这样的功能。 但如果您使用自己的类加载器(或扩展现有的类加载器),你可以添加此功能。 在任何情况下,不漂亮。