How do I read all classes from a Java package in t

2020-01-23 03:30发布

I need to read classes contained in a Java package. Those classes are in classpath. I need to do this task from a Java program directly. Do you know a simple way to do?

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

17条回答
走好不送
2楼-- · 2020-01-23 04:08
  1. Bill Burke has written a (nice article about class scanning] and then he wrote Scannotation.

  2. Hibernate has this already written:

    • org.hibernate.ejb.packaging.Scanner
    • org.hibernate.ejb.packaging.NativeScanner
  3. CDI might solve this, but don't know - haven't investigated fully yet

.

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

Also for annotations:

abstract class MyAnnotationQualifier
extends AnnotationLiteral<Entity> implements Entity {}
查看更多
smile是对你的礼貌
3楼-- · 2020-01-23 04:10

The most robust mechanism for listing all classes in a given package is currently ClassGraph, because it handles the widest possible array of classpath specification mechanisms, including the new JPMS module system. (I am the author.)

List<String> classNames;
try (ScanResult scanResult = new ClassGraph().whitelistPackages("my.package")
        .enableClassInfo().scan()) {
    classNames = scanResult.getAllClasses().getNames();
}
查看更多
疯言疯语
4楼-- · 2020-01-23 04:12

You could use the Reflections Project described here

It's quite complete and easy to use.

Brief description from the above website:

Reflections scans your classpath, indexes the metadata, allows you to query it on runtime and may save and collect that information for many modules within your project.

Example:

Reflections reflections = new Reflections(
    new ConfigurationBuilder()
        .setUrls(ClasspathHelper.forJavaClassPath())
);
Set<Class<?>> types = reflections.getTypesAnnotatedWith(Scannable.class);
查看更多
手持菜刀,她持情操
5楼-- · 2020-01-23 04:19

That functionality is still suspiciously missing from the Java reflection API as far as I know. You can get a package object by just doing this:

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

But as you probably noticed, that won't let you list the classes in that package. As of right now, you have to take sort of a more filesystem-oriented approach.

I found some sample implementations in this post

I'm not 100% sure these methods will work when your classes are buried in JAR files, but I hope one of those does it for you.

I agree with @skaffman...if you have another way of going about this, I'd recommend doing that instead.

查看更多
看我几分像从前
6楼-- · 2020-01-23 04:21

If you have Spring in you classpath then the following will do it.

Find all classes in a package that are annotated with 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;
}
查看更多
爷、活的狠高调
7楼-- · 2020-01-23 04:21

Here is another option, slight modification to another answer in above/below:

Reflections reflections = new Reflections("com.example.project.package", 
    new SubTypesScanner(false));
Set<Class<? extends Object>> allClasses = 
    reflections.getSubTypesOf(Object.class);
查看更多
登录 后发表回答