如何创建注释的实例

问题描述 投票:50回答:4

我正在尝试做一些Java注释魔术。我必须说我仍在追赶注释技巧,而且某些事情对我来说仍然不太清楚。

所以...我有一些带注释的类,方法和字段。我有一个方法,它使用反射对类运行一些检查并将一些值注入到类中。一切正常。

但是,我现在面临的情况是我需要一个注释的实例(可以这么说)。所以...注释不像常规接口,你不能做一个类的匿名实现。我知道了。我在这里看了一些关于类似问题的帖子,但我似乎无法找到我正在寻找的答案。

我基本上想得到一个注释的实例,并能够使用反射设置它的一些字段(我想)。有没有办法做到这一点?

java reflection annotations
4个回答
61
投票

好吧,显然没有什么比这更复杂了。真!

正如同事所指出的,你可以简单地创建一个匿名的注释实例(就像任何接口一样):

MyAnnotation:

public @interface MyAnnotation
{

    String foo();

}

调用代码:

class MyApp
{
    MyAnnotation getInstanceOfAnnotation(final String foo)
    {
        MyAnnotation annotation = new MyAnnotation()
        {
            @Override
            public String foo()
            {
                return foo;
            }

            @Override
            public Class<? extends Annotation> annotationType()
            {
                return MyAnnotation.class;
            }
        };

        return annotation;
    }
}

积分兑换Martin Grigorov


10
投票

Gunnar's answer中建议的代理方法已在GeAnTyRef中实现:

Map<String, Object> annotationParameters = new HashMap<>();
annotationParameters.put("name", "someName");
MyAnnotation myAnnotation = TypeFactory.annotation(MyAnnotation.class, annotationParameters);

这将产生一个等同于你得到的注释:

@MyAnnotation(name = "someName")

以这种方式生成的注释实例将与通常由Java生成的注释实例相同,并且它们的hashCodeequals已经正确实现了兼容性,因此没有像在接受的答案中直接实例化注释那样奇怪的警告。事实上,JDK内部使用相同的方法:sun.reflect.annotation.AnnotationParser#annotationForMap

库本身很小,没有依赖性。

披露:我是GeAnTyRef背后的开发人员。


7
投票

您可以使用注释代理,例如来自Hibernate Validator项目的this onethis one(免责声明:我是后者的提交者)。


5
投票

你可以使用sun.reflect.annotation.AnnotationParser.annotationForMap(Class, Map)

public @interface MyAnnotation {
    String foo();
}

public class MyApp {
    public MyAnnotation getInstanceOfAnnotation(final String foo) {
        MyAnnotation annotation = AnnotationParser.annotationForMap(
            MyAnnotation.class, Collections.singletonMap("foo", "myFooResult"));
    }
}

缺点:来自sun.*的类在更高版本中可能会发生变化(尽管此方法自Java 5以来具有相同的签名)并且不适用于所有Java实现,请参阅this discussion

如果这是一个问题:您可以使用自己的InvocationHandler创建一个通用代理 - 这正是AnnotationParser在内部为您做的事情。或者您使用自己的MyAnnotation实现定义here。在这两种情况下,你应该记住实现annotationType()equals()hashCode(),因为结果是专门针对java.lang.Annotation记录的。

© www.soinside.com 2019 - 2024. All rights reserved.