如何扩展Java注解?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22126851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:46:45  来源:igfitidea点击:

How to extend Java annotation?

javaannotations

提问by bvitaliyg

In my project I use pre-defined annotation @With:

在我的项目中,我使用预定义的注释@With

@With(Secure.class)
public class Test { //....

The source code of @With:

的源代码@With

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface With { 

    Class<?>[] value() default {};
}

I want to write custom annotation @Secure, which will have the same effect as @With(Secure.class). How to do that?

我想写自定义注解@Secure,效果和@With(Secure.class). 怎么做?



What if I do like this? Will it work?

如果我这样做怎么办?它会起作用吗?

@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}

回答by piotrek

From Java language specification, Chapter 9.6 Annotation Types:

来自 Java 语言规范,第 9.6 章注解类型

No extends clause is permitted. (Annotation types implicitly extend annotation.Annotation.)

不允许扩展子句。(注释类型隐式扩展annotation.Annotation。)

So, you can not extend an Annotation. you need to use some other mechanism or create a code that recognize and process your own annotation. Spring allows you to group other Spring's annotation in your own custom annotations. but still, no extending.

因此,您不能扩展 Annotation。您需要使用其他一些机制或创建一个代码来识别和处理您自己的注释。Spring 允许您在自己的自定义注解中组合其他 Spring 的注解。但仍然没有扩展。

回答by Halmackenreuter

As piotrek pointed out, you cannot extend Annotations in the sense of inheritance. Still, you can create Annotations that aggregate others:

正如 piotrek 指出的那样,您不能在继承的意义上扩展 Annotations。不过,您可以创建聚合其他注释的注释:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SuperAnnotation {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SubAnnotation {
    SuperAnnotation superAnnotation();
    String subValue();
}

Usage:

用法:

@SubAnnotation(subValue = "...", superAnnotation = @SuperAnnotation(value = "superValue"))
class someClass { ... }

回答by Muhammad Abdurrahman

@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}

This will work.

这将起作用。

回答by Eric Jiang

To expand on Muhammad Abdurrahman's answer--

扩展穆罕默德·阿卜杜拉赫曼的回答——

@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}

This does notwork by default but you canuse it in conjunction with Spring's AnnotationUtils.

这并不会在默认情况下工作,但你可以结合Spring的使用AnnotationUtils

See this SO answerfor an example.

有关示例,请参阅此 SO 答案

回答by user2210419

You can use annotation for annotation like this:

您可以使用 annotation 进行注释,如下所示:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@WithSecurityContext(factory = WithCustomUserSecurityContextFactory.class)
public @interface WithCustomUser {
  String username() default "[email protected]";
  String password() default "demo";
  String[] authorities() default {Authority.USER};
}

And define exact state in its "child"

并在其“孩子”中定义确切的状态

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@WithCustomUser(username = "[email protected]",
                password = "admin",
                authorities = {Authority.USER, Authority.ADMINISTRATOR})
public @interface WithAdminUser {
}

In this case you have a some kind of "state" and access to the parent annotation fields via reflection/aspect.

在这种情况下,您有某种“状态”并通过反射/方面访问父注释字段。

回答by Georgi Peev

So the provided answer from Eric Jiang is 100% working in my situation and she is: I need JMSListener ,but i want to hide the destination name:

所以 Eric Jiang 提供的答案在我的情况下 100% 有效,她是:我需要 JMSListener ,但我想隐藏目标名称:

@GetPlayerDataByUUIDListener
    public void getPlayerDataByUUID(Object message) {
        System.out.println("Im Here");
    }

`

`

@JmsListener(destination = PlayerStatisticsJMSConstants.GET_PLAYER_DATA_BY_UUID)
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface GetPlayerDataByUUIDListener {
}

So this is working perfectly ,and it is the same as:

所以这是完美的工作,它是相同的:

@JmsListener(destination = "example")
    @GetPlayerDataByUUIDListener
    public void getPlayerDataByUUID(Object message) {
        System.out.println("Im Here");
    }