2

Imagine that we have a class:User.java below package: src/service/model

And we can get the package (src/service/model) annotations using User.class.getPackage().getAnnotaions();

Then How can we get the parent package (src/service) annotations.

I don't know how to get package annotations in a skip level.

kozmo
  • 4,024
  • 3
  • 30
  • 48
Kesa_Wu
  • 47
  • 7

1 Answers1

3

You can get all packages in app and than filter required package to get Annotations:

String userPackName = User.class.getPackage().getName();      // src.service.model
int lastIndex = userPackName.lastIndexOf(".");
String parentPackName = userPackName.substring(0, lastIndex); // src.service
Annotation[] annotations = Arrays.stream(Package.getPackages())
                .filter(pack -> pack.getName().equals(parentPackName))
                .findFirst()
                .map(Package::getAnnotations)
                .orElseGet(() -> new Annotation[0]);

, but Package.getPackages() will only return the packages defined in the current class loader (any classes from root package (src/service) were loaded by current class loader).

java.lang.Package snippet:

@CallerSensitive
public static Package[] getPackages() {
    ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass());
    return cl != null ? cl.getPackages() : (Package[])BootLoader.packages().toArray((x$0) -> {
        return new Package[x$0];
    });
}

/** @deprecated */
@CallerSensitive
@Deprecated(
    since = "9"
)
public static Package getPackage(String name) {
    ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
    return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name);
}
kozmo
  • 4,024
  • 3
  • 30
  • 48
  • ```$xslt Optional obj1 = Arrays.stream(Package.getPackages()) .filter(pack -> pack.getName().equals("com.goods.center.backend.controller")) .findFirst() .map(Package::getAnnotations); Optional obj2 = Arrays.stream(Package.getPackages()) .filter(pack -> pack.getName().equals("com.goods.center.backend.controller.merchant")) .findFirst() .map(Package::getAnnotations); ``` annother problem encountered. obj1 is empty.obj2 is not empty. Why obj1 is empty? – Kesa_Wu May 14 '20 at 10:21
  • The `java.lang.Package.getPackages()` method gets all the packages currently known for the caller's ClassLoader instance. Those packages correspond to classes loaded via or accessible by name to that ClassLoader instance. If the caller's ClassLoader instance is the bootstrap ClassLoader instance, which may be represented by null in some implementations, only packages corresponding to classes loaded by the bootstrap ClassLoader instance will be returned. – kozmo May 14 '20 at 10:31
  • 1
    The caller is the code in this answer. So it is surely not loaded by the bootstrap loader. But why using this stream to search all packages? Why not just use `Annotation[] annotations = Package.getPackage(parentPackName).getAnnotations();`? – Holger May 14 '20 at 12:41
  • `@Deprecated(since="9") public static Package getPackage​(String name)`: https://docs.oracle.com/javase/9/docs/api/java/lang/Package.html#getPackage-java.lang.String- – kozmo May 14 '20 at 12:52
  • @kozmo@Holger Thank you for your instructions. The last one : If no class under "com.service",despite many class under "com.service.model",the API Package.getPackage("com.service") will return null.I don't know why. – Kesa_Wu May 15 '20 at 01:03
  • @Kesa_Wu - `Package.getPackage(...)` will only return a non-null value if the current ClassLoader is already aware of the package. `.getPackage(...)` & `.getPackage() `use the same approach to get ClassLoader: `ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass())`. Look at https://stackoverflow.com/questions/10993418/package-getpackage-in-java-returning-null – kozmo May 15 '20 at 05:45
  • @kozmo Sorry,in the upper case,the API Package.getPackage("com.service") returned Optional.Empty.I guess it is caused by the package "com.service" that no classes loaded from it. – Kesa_Wu May 15 '20 at 06:45
  • @Kesa_Wu - y. -> `Package.getPackage("com.service")` return `null` – kozmo May 15 '20 at 06:53
  • @kozmo Thank you.I just got messed up. and I am clear now. – Kesa_Wu May 15 '20 at 07:00