reflections icon indicating copy to clipboard operation
reflections copied to clipboard

Repeatable Annotations

Open ssmoss opened this issue 7 years ago • 3 comments

I am using reflections version 0.9.10 with javassist version 3.20.0-GA. I have the following annotations and classes:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Names {
    Name[] value() default {};
}

@Repeatable(Names.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Names {
    String name();
}

@Name(name = "foo")
public class SingleName extends BaseClass {}

@Name(name = "foo")
@Name(name = "bar")
public class MultiName extends BaseClass {}

I am trying to look up all classes that have occurrence of the @Name annotation. I used the following to try to do that:

new Reflections(BaseClass.class.getPackage().getName()).getTypesAnnotatedWith(Name.class)

The above only works when the class has as single @Name. To get a classes with more than one occurrence of the @Name I need to use the following:

new Reflections(BaseClass.class.getPackage().getName()).getTypesAnnotatedWith(Names.class)

I ideally I would like to not have to merge the results from both of these calls. It seems that java supports that because when I do the following:

SingleName.class.getAnnotationsByType(Name.class); //Return an array of one
MultiName.class.getAnnotationsByType(Name.class); //Returns an array of two

Does reflections currently support this and I am using it wrong? If not would it be possible to add support for repeatable annotations? Thanks.

ssmoss avatar Jul 27 '16 17:07 ssmoss

Considering how @Repeatable annotations are declared, we can't easily or consistently tell if an annotation is a container.

So, that removes the option of doing it at scan time, but it would be possible doing it at retrieval. Just check if the given annotation declares a @Repeatable and merge the results.

Jezza avatar Jan 23 '17 10:01 Jezza

What's the status of this? It would be really useful!

heruan avatar Mar 10 '18 16:03 heruan

check the bytecode, javap -verbose MultiName.class, something like following,

Classfile /Users/honwhywang/github/reflections/target/test-classes/org/reflections/repeatable/MultiName.class
  Last modified 2019-3-13; size 471 bytes
  MD5 checksum fb5f9f4fa77213e01322598ad6727f98
  Compiled from "MultiName.java"
public class org.reflections.repeatable.MultiName
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#20         // java/lang/Object."<init>":()V
   #2 = Class              #21            // org/reflections/repeatable/MultiName
   #3 = Class              #22            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               Lorg/reflections/repeatable/MultiName;
  #11 = Utf8               SourceFile
  #12 = Utf8               MultiName.java
  #13 = Utf8               RuntimeVisibleAnnotations
  #14 = Utf8               Lorg/reflections/repeatable/Names;
  #15 = Utf8               value
  #16 = Utf8               Lorg/reflections/repeatable/Name;
  #17 = Utf8               name
  #18 = Utf8               foo
  #19 = Utf8               bar
  #20 = NameAndType        #4:#5          // "<init>":()V
  #21 = Utf8               org/reflections/repeatable/MultiName
  #22 = Utf8               java/lang/Object
{
  public org.reflections.repeatable.MultiName();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lorg/reflections/repeatable/MultiName;
}
SourceFile: "MultiName.java"
RuntimeVisibleAnnotations:
  0: #14(#15=[@#16(#17=s#18),@#16(#17=s#19)])

two @Name was compiled to one @Names Array with two elements java version,

java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

honwhy avatar Mar 13 '19 16:03 honwhy