如何从一个Java包中的类路径中读取所有类?(How do I read all classes f

2019-07-18 21:19发布

我需要阅读包含在Java包类。 这些类是在类路径中。 我需要直接从Java程序做这个任务。 你知道一个简单的方法呢?

List<Class> classes = readClassesFrom("my.package")

Answer 1:

如果你有春天在你的classpath那么下面会做。

查找被标注了一个XmlRootElement将包中的所有类:

private List<Class> findMyTypes(String basePackage) throws IOException, ClassNotFoundException
{
    ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);

    List<Class> candidates = new ArrayList<Class>();
    String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                               resolveBasePackage(basePackage) + "/" + "**/*.class";
    Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
    for (Resource resource : resources) {
        if (resource.isReadable()) {
            MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
            if (isCandidate(metadataReader)) {
                candidates.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
            }
        }
    }
    return candidates;
}

private String resolveBasePackage(String basePackage) {
    return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
}

private boolean isCandidate(MetadataReader metadataReader) throws ClassNotFoundException
{
    try {
        Class c = Class.forName(metadataReader.getClassMetadata().getClassName());
        if (c.getAnnotation(XmlRootElement.class) != null) {
            return true;
        }
    }
    catch(Throwable e){
    }
    return false;
}


Answer 2:

你可以使用所描述的思考项目在这里

这是很完整的,易于使用。

从上述网站简介:

反思扫描你的类路径,索引元数据,使您可以查询它在运行时,可能保存和收集信息,为您的项目中的许多模块。

例:

Reflections reflections = new Reflections(
    new ConfigurationBuilder()
        .setUrls(ClasspathHelper.forJavaClassPath())
);
Set<Class<?>> types = reflections.getTypesAnnotatedWith(Scannable.class);


Answer 3:

我用这一个,它与文件或JAR档案

public static ArrayList<String>getClassNamesFromPackage(String packageName) throws IOException{
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    URL packageURL;
    ArrayList<String> names = new ArrayList<String>();;

    packageName = packageName.replace(".", "/");
    packageURL = classLoader.getResource(packageName);

    if(packageURL.getProtocol().equals("jar")){
        String jarFileName;
        JarFile jf ;
        Enumeration<JarEntry> jarEntries;
        String entryName;

        // build jar file name, then loop through zipped entries
        jarFileName = URLDecoder.decode(packageURL.getFile(), "UTF-8");
        jarFileName = jarFileName.substring(5,jarFileName.indexOf("!"));
        System.out.println(">"+jarFileName);
        jf = new JarFile(jarFileName);
        jarEntries = jf.entries();
        while(jarEntries.hasMoreElements()){
            entryName = jarEntries.nextElement().getName();
            if(entryName.startsWith(packageName) && entryName.length()>packageName.length()+5){
                entryName = entryName.substring(packageName.length(),entryName.lastIndexOf('.'));
                names.add(entryName);
            }
        }

    // loop through files in classpath
    }else{
    URI uri = new URI(packageURL.toString());
    File folder = new File(uri.getPath());
        // won't work with path which contains blank (%20)
        // File folder = new File(packageURL.getFile()); 
        File[] contenuti = folder.listFiles();
        String entryName;
        for(File actual: contenuti){
            entryName = actual.getName();
            entryName = entryName.substring(0, entryName.lastIndexOf('.'));
            names.add(entryName);
        }
    }
    return names;
}


Answer 4:

春天已经实现在一个优秀的类路径搜索功能PathMatchingResourcePatternResolver 。 如果您使用classpath* :前缀,你可以找到所有的资源,包括在给定的层次结构类,如果你想,即使过滤。 然后你可以使用的儿童AbstractTypeHierarchyTraversingFilterAnnotationTypeFilterAssignableTypeFilter过滤无论是在类级别的注解或他们实现接口的资源。



Answer 5:

的Java 1.6.0_24:

public static File[] getPackageContent(String packageName) throws IOException{
    ArrayList<File> list = new ArrayList<File>();
    Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
                            .getResources(packageName);
    while (urls.hasMoreElements()) {
        URL url = urls.nextElement();
        File dir = new File(url.getFile());
        for (File f : dir.listFiles()) {
            list.add(f);
        }
    }
    return list.toArray(new File[]{});
}

这种溶液的内测试EJB环境。



Answer 6:

Scannotation和思考使用类路径扫描的方法:

Reflections reflections = new Reflections("my.package");
Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);

另一种方法是使用Java的可插入注释处理API编写注释处理器将收集所有注解的类在编译时和建立运行时使用的索引文件。 该机制在执行ClassIndex库:

Iterable<Class> classes = ClassIndex.getPackageClasses("my.package");


Answer 7:

该功能仍怀疑从Java反射API失踪据我所知。 您可以通过只是在做这得到一个包对象:

Package packageObj = Package.getPackage("my.package");

但是,正如你可能已经注意到了,不会让你在包列表中的类。 截至目前,你必须采取某种更加面向文件系统的方法。

我发现了一些示例实现在这个岗位

我不是100%肯定,当你的类埋在JAR文件这些方法的工作,但我希望其中的一个会为你。

我同意@skaffman ......如果你有去这个另一种方式,我建议你这样做来代替。



Answer 8:

你可以试试我的图书馆FastClasspathScanner 。 扫描类路径并不像检查一样简单java.class.path属性,并递归扫描上课那里,因为有classpath中可以指定多种方式(例如,你可以添加Class-Path条目的jar文件的清单)。 使用Class.forName()实际上初始化类,这可能不是你想要什么,等FastClasspathScanner处理这些复杂的你。

要列举包中的所有类,请执行以下操作:

String packageName = "my.package";
Set<String> classNames = new FastClassPathScanner(packageName)
    .scan()
    .getNamesOfAllClasses();
String packageNamePrefix = packageName + ".";
for (String className : classNames) {
    if (className.startsWith(packageNamePrefix) {
        System.out.println("Found class: " + className);
   }
}

你需要检查if (className.startsWith(packageNamePrefix)因为如果一个类是指另一个类(例如作为超类),它的白名单包前缀外my.package ,它会被包含在返回的集.getNamesOfAllClasses()



Answer 9:

eXtcos看起来很有希望。 想象一下,你想找到的所有类是:

  1. 从类“组件”扩展,并将它们存储
  2. 被标注为“MyComponent的”,并
  3. 在“通用”包。

随着eXtcos这就是这么简单

ClasspathScanner scanner = new ClasspathScanner();
final Set<Class> classStore = new ArraySet<Class>();

Set<Class> classes = scanner.getClasses(new ClassQuery() {
    protected void query() {
        select().
        from(“common”).
        andStore(thoseExtending(Component.class).into(classStore)).
        returning(allAnnotatedWith(MyComponent.class));
    }
});


Answer 10:

  1. 比尔·伯克已经写了(好的文章有关类扫描],然后他写Scannotation

  2. Hibernate有这个已经写:

    • org.hibernate.ejb.packaging.Scanner
    • org.hibernate.ejb.packaging.NativeScanner
  3. CDI可能会解决这个问题,但不知道-有没有充分的调查尚未

@Inject Instance< MyClass> x;
...
x.iterator() 

此外注解:

abstract class MyAnnotationQualifier
extends AnnotationLiteral<Entity> implements Entity {}


Answer 11:

我碰巧已经实现它,它在大多数情况下工作。 既然是长期的,我把它放在一个文件在这里 。

我们的想法是找到类的源文件是在大多数情况下可用的位置(已知的一个例外是JVM类文件 - 据我测试过)。 如果代码是在一个目录,通过扫描所有文件,并只点类文件。 如果代码是一个JAR文件,扫描所有条目。

这种方法只能时使用:

  1. 你有一类就是在要发现同一个包,这个类被称为SeedClass。 例如,如果要列出“java.io”的所有类,种子类可能是java.io.File

  2. 你的类在目录或JAR文件时,它具有源文件信息(而不是源代码文件,只是源文件)。 至于我已经试过了,它的工作几乎是100%,除了JVM类(这些类来与JVM)。

  3. 你的程序必须有权限访问这些类的ProtectionDomain。 如果你的程序是本地加载,应该没有问题。

我测试过该程序只为我的正常使用,所以它可能仍然有问题。

我希望这有帮助。



Answer 12:

这是另一种选择,稍加修改,以高于/低于另一个答案:

Reflections reflections = new Reflections("com.example.project.package", 
    new SubTypesScanner(false));
Set<Class<? extends Object>> allClasses = 
    reflections.getSubTypesOf(Object.class);


Answer 13:

回来时,小应用程序是共同的地方,一个可能classpath中的URL。 当类加载器所需的一类,它会搜索的类路径上的所有位置,包括HTTP资源。 因为你可以有类似的东西在类路径中的URL和目录,有没有简单的方法来获取类的最终名单。

但是,你可以得到相当接近。 一些Spring库现在正在做这件事。 你可以在类路径上所有jar的,并打开它们像文件。 然后,你可以把此文件列表,并创建一个包含类的数据结构。



Answer 14:

该项目ldapbeans提供了一个类扫描仪是做到这一点。



Answer 15:

使用依赖行家:

groupId: net.sf.extcos
artifactId: extcos
version: 0.4b

然后使用此代码:

ComponentScanner scanner = new ComponentScanner();
        Set classes = scanner.getClasses(new ComponentQuery() {
            @Override
            protected void query() {
                select().from("com.leyton").returning(allExtending(DynamicForm.class));
            }
        });


Answer 16:

如果你已经在使用番石榴,您可以使用类路径。 点击这里,查看文档: https://google.github.io/guava/releases/17.0/api/docs/com/google/common/reflect/ClassPath.html



Answer 17:

布伦特 - 联想的原因是一个办法是与事实,你的CLASSPATH的任何组件上的任何类可以在任何包(除了爪哇/使用javax)宣布自己做。 因此,那里只是没有在给定的“一揽子”的所有类的映射,因为没有人知道,也不知道。 你可以更新一个jar文件,明天删除或添加类。 这就像试图获得任命John /乔恩/约翰在世界上的所有国家的所有的人的名单 - 我们没有人是无所不知的,因此我们没有人永远不会有正确的答案。



文章来源: How do I read all classes from a Java package in the classpath?