简体   繁体   English

Reflections库是否忽略RetentionPolicy

[英]Does Reflections library ignore the RetentionPolicy

For understanding of the Java annotations I tried some hands on and got few doubts, even though looking at execution I am still confused. 为了理解Java批注,尽管尝试了执行,但我仍然感到困惑,我尝试了一些尝试并获得了很少的疑问。 Here is what I am doing. 这是我在做什么。 Define a Annotation 定义注释

@Retention(RetentionPolicy.CLASS)
@Target(value=ElementType.TYPE)
public @interface Command {

}

Now I initialize the commands 现在我初始化命令

       Reflections reflections = new Reflections(CMDS_PACKAGE);
       Set<Class<?>> allClasses = reflections.getTypesAnnotatedWith(Command.class); // line 2

        for (Class clazz : allClasses) {
            MYCommand cmd = (MYCommand) clazz.newInstance();
            System.out.println(cmd.getClass().getAnnotation(Command.class));// line 6
            log.info("loading Command [ {} ]", clazz.getCanonicalName());
        }

when I run the program line 6 displays null . 当我运行程序时,第6行显示null When the policy is RetentionPolicy.RUNTIME line 6 displays the correct Command. 当策略为RetentionPolicy.RUNTIME第6行显示正确的命令。

During this process the line 2 is still giving me correct Annotated class irrespective of policy. 在此过程中,第2行仍然为我提供了正确的带注释的类,与策略无关。 So does it mean that the Reflection Library is ignoring the RetentionPolicy 这是否意味着反射忽略了RetentionPolicy

I am really confused even though reading most of tutorials. 即使阅读了大多数教程,我也很困惑。

The question for me actually is that , why is this different behaviour? 对我来说实际上的问题是,为什么这种不同的行为? When annotated with RetentionPolicy.CLASS policy It should not have given me at runtime. RetentionPolicy.CLASS策略注释时,它在运行时不应该给我。 Is my understanding wrong or can anyone please share there valuable inputs on the understanding of these both. 我的理解是错误的,还是任何人都可以在那里分享对这两者的理解的宝贵意见。

In the first place, the RetentionPolicy dictates what a conforming compiler has to do. 首先, RetentionPolicy规定了合格的编译器必须执行的操作。 Annotation s with RetentionPolicy.SOURCE do not make it into the class file while the other two, RetentionPolicy.CLASS and RetentionPolicy.RUNTIME , are stored within the class file but using different attributes to allow to make a distinction between them when reading the class file. 带有RetentionPolicy.SOURCE Annotation不会进入类文件,而其他两个RetentionPolicy.CLASSRetentionPolicy.RUNTIME存储在类文件中,但是使用不同的属性允许在读取类文件时进行区分。

The documentation of RetentionPolicy.CLASS says: RetentionPolicy.CLASS文档说:

Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time. 注释由编译器记录在类文件中,但VM在运行时无需保留。 This is the default behavior. 这是默认行为。

Here, the responsibility is clearly documented, the VM shall not retain them and the Reflection API built into the JRE conforms to it. 在此,明确记录了责任, VM不应保留责任,并且JRE内置的Reflection API与此相符。 Though “need not be retained” does not sound like a strong requirement. 尽管“不需要保留”听起来并不像是一个强烈的要求。

But 3rd party libraries like the Reflection Library you are using are free to implement whatever they want when parsing a class file. 但是,您正在使用的第三方库(例如反射库)可以自由地解析语法文件时实现他们想要的任何东西。 Since the documentation for the method you have called simply says: “get types annotated with a given annotation”, the behavior isn't wrong as the type has that annotation. 由于您调用的方法的文档仅说:“获取使用给定注释进行注释的类型”,因此行为没有错,因为该类型具有该注释。

And you are able to find out the RetentionPolicy of that Annotation even before invoking that method by analyzing the Annotations of the Annotation . 你能找出RetentionPolicy是的Annotation甚至通过分析调用该方法之前Annotations的的Annotation So it makes no sense invoking the method when you already know that the annotation has the RetentionPolicy.CLASS and then bother because the method does something instead of nothing. 因此,当您已经知道注释具有RetentionPolicy.CLASS并随后麻烦时,调用该方法是没有意义的,因为该方法执行的是操作而不是不执行任何操作。

But, of course, it would be better if that behavior was documented completely. 但是,当然,最好将这种行为完整记录下来。 So you might ask the author of that 3rd party library to improve the documentation. 因此,您可以要求该第三方库的作者改进文档。

Yes, the Reflections library (not Reflection, but Reflection* s *) does ignore the visibility of annotations by default. 是的, 反射库 (不是反射,而是反射* s *)默认情况下不会忽略注释的可见性。 This can be changed using the org.reflections.adapters.JavassistAdapter#includeInvisibleTag flag. 可以使用org.reflections.adapters.JavassistAdapter#includeInvisibleTag标志进行更改。 Something like: 就像是:

JavassistAdapter mdAdapter = new JavassistAdapter();
mdAdapter.includeInvisibleTag = false;

new Reflections(new ConfigurationBuilder()
    ...
    .setMetadataAdapter(mdAdapter)
    ...

Another option would be to use the JavaReflectionAdapter instead. 另一种选择是改为使用JavaReflectionAdapter。

HTH HTH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM