如何扩展Java注释?

问题描述 投票:26回答:6

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

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

@With的源代码:

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

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

我想编写自定义注释@Secure,它将与@With(Secure.class)具有相同的效果。怎么做?


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

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

}
java annotations
6个回答
17
投票

从Java语言规范,Chapter 9.6 Annotation Types

不允许使用扩展条款。 (注释类型隐式扩展annotation.Annotation。)

因此,您无法扩展Annotation。您需要使用其他一些机制或创建识别和处理您自己的注释的代码。 Spring允许您在自己的自定义注释中对其他Spring的注释进行分组。但仍然没有扩展。


17
投票

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

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

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

用法:

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

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

}

这会奏效。


3
投票

扩大穆罕默德·阿卜杜拉赫曼的回答 -

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

}

这在默认情况下不起作用,但您可以将它与Spring的AnnotationUtils结合使用。

有关示例,请参阅this SO answer


1
投票

您可以像这样使用注释注释:

@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};
}

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

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

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


0
投票

所以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 {
}

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

@JmsListener(destination = "example")
    @GetPlayerDataByUUIDListener
    public void getPlayerDataByUUID(Object message) {
        System.out.println("Im Here");
    }
© www.soinside.com 2019 - 2024. All rights reserved.