将注释属性传递给元注释

Tom*_*yre 29 java annotations

假设我有一个属性的注释:

@Named(name = "Steve")
private Person person
Run Code Online (Sandbox Code Playgroud)

我想创建一个带有多个元注释的复合注释,包括带有属性的元注释

@Named
@AnotherAnnotation
@YetAnotherAnnotation
public @interface CompoundAnnotation {

    ...
}
Run Code Online (Sandbox Code Playgroud)

有没有办法可以将属性传递给复合注释到其中一个元注释?

例如,像这样:

@CompoundAnnotation(name = "Bob")
private Person person;
Run Code Online (Sandbox Code Playgroud)

这相当于,但比方便得多

@Named(name = "Bob")
@AnotherAnnotation
@YetAnotherAnnotation
private Person person;
Run Code Online (Sandbox Code Playgroud)

谢谢!

PS为我糟糕的示例注释选择道歉 - 我没有javax.inject.@ Named注释,只是一些具有属性的任意注释.


谢谢大家的回答/评论.

这似乎是不可能的.然而,恰好有一个简单的解决方案,我将分享以下情况,如果它可以帮助任何人:

我正在使用Spring,并希望创建自己的注释,将@Component作为元注释,从而通过组件扫描自动检测.但是,我还希望能够设置BeanName属性(对应于@Component中的value属性),这样我就可以拥有自定义bean名称.

好吧,事实证明Spring的有思想的人可以做到这一点 - AnnotationBeanNameGenerator将采用它传递的任何注释的'value'属性并将其用作bean名称(当然,默认情况下,它将只传递@Component的注释或将@Component作为元注释.回想起来,这应该从一开始就很明显 - 这就是使用@Component作为元注释的现有注释,例如@Service和@Registry,可以提供bean名称.

希望对某人有用.尽管如此,我仍然认为这是不可能的,这是一种耻辱!

Maa*_*rak 27

几年之后,由于你正在使用Spring,你现在要求的是使用@AliasFor注释的可能性.

例如:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration
@ActiveProfiles("test")
public @interface SpringContextTest {

    @AliasFor(annotation = SpringApplicationConfiguration.class, attribute = "classes")
    Class<?>[] value() default {};

    @AliasFor("value")
    Class<?>[] classes() default {};
}
Run Code Online (Sandbox Code Playgroud)

现在你可以用你的测试来注释@SpringContextTest(MyConfig.class),而令人惊奇的是它实际上以你期望的方式工作.


Gra*_*ray 8

有没有办法可以将属性传递给复合注释到其中一个元注释?

我认为简单的答案是"不".没有办法询问Person它上面有什么注释@Named,例如.

更复杂的答案是您可以链接注释,但您必须通过反射来研究这些注释.例如,以下工作:

@Bar
public class Foo {
    public static void main(String[] args) {
        Annotation[] fooAnnotations = Foo.class.getAnnotations();
        assertEquals(1, fooAnnotations.length);
        for (Annotation annotation : fooAnnotations) {
            Annotation[] annotations =
                annotation.annotationType().getAnnotations();
            assertEquals(2, annotations.length);
            assertEquals(Baz.class, annotations[0].annotationType());
        }
    }

    @Baz
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Bar {
    }

    @Retention(RetentionPolicy.RUNTIME)
    public @interface Baz {
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,以下语句将返回null:

// this always returns null
Baz baz = Foo.class.getAnnotation(Baz.class)
Run Code Online (Sandbox Code Playgroud)

这意味着正在寻找@Baz注释的任何第三方类都不会看到它.