如何在jar包运行时从package-info.java中访问包级别的注解?

7

我该如何访问类路径中jar包内的所有package-info类?我想要访问这些类中使用的包级别注解。

我想执行以下步骤:

  1. 找到所有的package-info.java类
  2. 获取它们的包
  3. 获取注解@PackageOwner

Javadoc 包可能会有帮助。 - planetmaker
4个回答

6

有一个更简单的解决方案,不涉及外部API。您可以从位于您想要注释的包中的类获取Package对象。然后通过在该包上调用方法getAnnotations()来获取这些注释:

import java.lang.annotation.Annotation;

public class PackageAnnotationsTest {

    public static void main(String[] args) {
        Package myPackage = AClassInMyPackage.class.getPackage();
        Annotation[] myPackageAnnotations = myPackage.getAnnotations();
        System.out.println("Available annotations for package : " + myPackage.getName());
        for(Annotation a : myPackageAnnotations) {
            System.out.println("\t * " + a.annotationType());
        }
    }
}

感谢这个链接,它帮助我回答了这个问题。我先看了这个线程和Parikshit的答案,但我不想使用外部api。请点击此链接查看更多信息。

我的问题是基础包中有许多“package-info”类。此外,我无法使用“package-info.class.getPackage()”,因为编译器会抛出错误。 - Parikshit
我真的不太明白。每个包只能有一个package-info.java文件。访问该文件中的注释的方法是在该包的实际类上调用getPackage().getAnnotations(),而不是该包本身的“类”(顺便说一下,它并不是一个真正的类)。 - altaroinj
假设我有一个名为“com.mercedes.car”的包,我认为它是我的基础包。对于该包,我只能有一个package-info.java文件。但是我可以在“com.mercedes.car.engine”中拥有一个单独的包。此外,我不知道包中存在哪些类。因此不存在AClassInMyPackage.class.getPackage()的问题。 - Parikshit
我假设你的问题在于如何从package-info.class文件中检索信息,而不是如何找到所有包并读取它们关联的注释。 - altaroinj

5

Guava 14+拯救了我们 :)

以下代码可行

public class OwnerFinder {
    public static void main(String[] args) {
        try {
            ClassPath classPath = ClassPath.from(OwnerFinder.class.getClassLoader());
            classPath.getTopLevelClassesRecursive("com.somepackage")
                    .stream()
                    .filter(c -> c.getSimpleName().equals("package-info"))
                    .map(c -> c.load().getPackage().getAnnotation(PackageOwner.class))
                    .forEach(a -> System.out.println(a.owner()));

        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

包信息文件package-info.java的注解应用如下:

@PackageOwner(owner = "shaikhm")
package com.somepackage;

1
附加说明:您的注释本身必须使用@Retention(RetentionPolicy.RUNTIME)进行注释,以便通过此机制进行拾取。 - Luke

1
也许你可以尝试使用 reflections 库。

https://github.com/ronmamo/reflections

Reflections 的典型用法如下:
Reflections reflections = new Reflections("my.project");

Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);

Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);

我意识到找到package-info类行不通。我不能使用reflections.getSubTypesOf(package-info.class)。它会导致编译错误。可能是因为package-info没有任何类结构。希望有一个API可以访问已注释的包。我尝试了Package.getPackages(),但它只返回已加载类的包。 - Parikshit

1
如果您需要动态加载一个Package,而且无法直接引用现有类来获取Package,那么可以使用以下方法加载package-info类并检索注释:
Package pkg = Class.forName(packageName + ".package-info").getPackage();
PackageOwner packageOwner = pkg.getAnnotation(PackageOwner.class);

这样做可以避免使用外部依赖,而且您不需要了解目标包中的任何类。

需要注意的是,您不必使用getPackage,您也可以从package-info Class对象中获取注释,这就是Package#getAnnotation在内部执行的操作。 - Clashsoft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接