Java 如何创建注释的实例

Java 如何创建注释的实例,java,reflection,annotations,Java,Reflection,Annotations,我正在尝试做一些Java注释魔术。我必须说,我仍在掌握注释技巧,某些事情对我来说还不是很清楚 所以。。。我有一些带注释的类、方法和字段。我有一个方法,它使用反射对类运行一些检查,并向类中注入一些值。这一切都很好 然而,我现在面临一个需要注释实例的情况。所以注释与常规接口不同,您不能对类进行匿名实现。我明白了。我在这里查阅了一些关于类似问题的帖子,但我似乎找不到我所寻找的答案 我基本上希望获得注释的名称和实例,并能够使用反射设置它的一些字段(我想)。有没有办法做到这一点?嗯,显然没那么复杂newu

我正在尝试做一些Java注释魔术。我必须说,我仍在掌握注释技巧,某些事情对我来说还不是很清楚

所以。。。我有一些带注释的类、方法和字段。我有一个方法,它使用反射对类运行一些检查,并向类中注入一些值。这一切都很好

然而,我现在面临一个需要注释实例的情况。所以注释与常规接口不同,您不能对类进行匿名实现。我明白了。我在这里查阅了一些关于类似问题的帖子,但我似乎找不到我所寻找的答案


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

嗯,显然没那么复杂<真的

正如一位同事所指出的,您可以简单地创建注释的匿名实例(如任何接口),如下所示:

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;
    }
}
classmyapp
{
MyAnnotation GetInstanceOffNotation(最终字符串foo)
{
MyAnnotation=新建MyAnnotation()
{
@凌驾
公共字符串foo()
{
返回foo;
}
@凌驾

public Class您可以使用诸如Hibernate Validator项目中的注释代理(免责声明:我是此项目的提交者)。

您可以使用
sun.reflect.annotation.AnnotationParser.annotationForMap(类,映射)

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


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

记录了代理方法,如中所建议,已在中实现:

以这种方式生成的注释实例的行为与Java通常生成的注释实例完全相同,并且它们的
hashCode
equals
已经正确地实现了兼容性,因此没有像在接受的答案中直接实例化注释那样奇怪的警告h:

库本身很小,没有依赖性(并且不依赖于JDK内部API)


披露:我是GeantyRef的开发人员。

在Apache Commons的帮助下使用代理方法相当粗糙


publicstatic(可能也是),没有使用内部Java API的缺点,如

我这样做是为了在我的焊接单元测试中添加注释参考:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ METHOD, FIELD, PARAMETER })
public @interface AuthenticatedUser {

    String value() default "foo";

    @SuppressWarnings("all")
    static class Literal extends AnnotationLiteral<AuthenticatedUser> implements AuthenticatedUser {

        private static final long serialVersionUID = 1L;

        public static final AuthenticatedUser INSTANCE = new Literal();

        private Literal() {
        }

        @Override
        public String value() {
            return "foo";
        }
    }
}
@限定符
@保留(RetentionPolicy.RUNTIME)
@目标({方法,字段,参数})
public@interface AuthenticatedUser{
字符串值()默认为“foo”;
@抑制警告(“全部”)
静态类文字扩展AnnotationLiteral实现AuthenticatedUser{
私有静态最终长serialVersionUID=1L;
public static final AuthenticatedUser实例=new Literal();
私有文本(){
}
@凌驾
公共字符串值(){
返回“foo”;
}
}
}
用法:

Bean<?> createUserInfo() {
    return MockBean.builder()
            .types(UserInfo.class)
            .qualifiers(AuthenticatedUser.Literal.INSTANCE)
            .create((o) -> new UserInfo())
            .build();
}
Bean createUserInfo(){
返回MockBean.builder()
.types(UserInfo.class)
.qualifiers(AuthenticatedUser.Literal.INSTANCE)
.create((o)->newuserinfo())
.build();
}

您也可以愚蠢地(但简单地)创建一个虚拟注释目标并从中获取它

@MyAnnotation(foo="bar", baz=Blah.class)
private static class Dummy {}

创建以方法/参数为目标的注释实例可能要复杂一些,但是这种方法的好处是获得注释实例,就像JVM通常所做的那样。
不用说,这是最简单的方法。

@Gunnar的答案是大多数Web服务最简单的方法,因为我们已经有了hibernate, 例如
KafkaListener KafkaListener=new org.hibernate.validator.internal.util.annotation.AnnotationDescriptor.Builder(KafkaListener.class,ImmutableMap.of(“主题”,新字符串[]{“我的主题”})).build().getAnnotation();
和所有其他属性将保持默认状态。

您无法实例化或修改批注。在运行代码时批注已经存在。您只能检索它们。您可以给出一些代码示例来说明您正在尝试执行的操作吗?您尝试过getAnnotation()吗可以在java.lang.Class/java.lang.reflect.Method中找到有趣的问题。我试着四处看看,得到了这些。只要看看拉尔夫的第一个答案。我想应该可以。这会有帮助吗?你试过getClass().getAnnotations()了吗?我不想检查一个类是否用某个注释进行了注释。我已经使用反射实现了注入的这一部分。我有一个特例,我必须将
MyAnnotation
添加到
Set
中,我没有注释的实例。嗯,看起来你也需要实现。大概是这样只需返回
MyAnnotation.class
。值得注意的是,我实际上让IDE生成了方法,但没有注意到它也实现了这些方法。它只需返回
null
,就可以工作了。我已经将它设置为注释的类类型,尽管我不确定它到底应该是什么。警告:匿名实例MyAnnotation的e是类的实例,而不是annotation,i
public static <A extends Annotation> A mockAnnotation(Class<A> annotationClass, Map<String, Object> properties) {
    return (A) Proxy.newProxyInstance(annotationClass.getClassLoader(), new Class<?>[] { annotationClass }, (proxy, method, args) -> {
        Annotation annotation = (Annotation) proxy;
        String methodName = method.getName();

        switch (methodName) {
            case "toString":
                return AnnotationUtils.toString(annotation);
            case "hashCode":
                return AnnotationUtils.hashCode(annotation);
            case "equals":
                return AnnotationUtils.equals(annotation, (Annotation) args[0]);
            case "annotationType":
                return annotationClass;
            default:
                if (!properties.containsKey(methodName)) {
                    throw new NoSuchMethodException(String.format("Missing value for mocked annotation property '%s'. Pass the correct value in the 'properties' parameter", methodName));
                }
                return properties.get(methodName);
        }
    });
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ METHOD, FIELD, PARAMETER })
public @interface AuthenticatedUser {

    String value() default "foo";

    @SuppressWarnings("all")
    static class Literal extends AnnotationLiteral<AuthenticatedUser> implements AuthenticatedUser {

        private static final long serialVersionUID = 1L;

        public static final AuthenticatedUser INSTANCE = new Literal();

        private Literal() {
        }

        @Override
        public String value() {
            return "foo";
        }
    }
}
Bean<?> createUserInfo() {
    return MockBean.builder()
            .types(UserInfo.class)
            .qualifiers(AuthenticatedUser.Literal.INSTANCE)
            .create((o) -> new UserInfo())
            .build();
}
@MyAnnotation(foo="bar", baz=Blah.class)
private static class Dummy {}
final MyAnnotation annotation = Dummy.class.getAnnotation(MyAnnotation.class)