将注释属性传递给元注释

时间:2012-04-10 11:02:00

标签: java annotations

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

@Named(name = "Steve")
private Person person

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

@Named
@AnotherAnnotation
@YetAnotherAnnotation
public @interface CompoundAnnotation {

    ...
}

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

例如,像这样:

@CompoundAnnotation(name = "Bob")
private Person person;

相当于,但比

更方便
@Named(name = "Bob")
@AnotherAnnotation
@YetAnotherAnnotation
private Person person;

谢谢!

对于我对示例注释的选择不好,PS道歉 - 我没有javax.inject。@注释注释,只是一些具有属性的任意注释。


感谢大家的回答/评论。

似乎无法做到这一点。然而,恰好有一个简单的解决办法,我会分享,如果它可以帮助任何人:

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

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

希望对某人有用。我仍然认为这是不可能的,但这不是更普遍的可能!

2 个答案:

答案 0 :(得分:24)

几年后,由于你正在使用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 {};
}

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

答案 1 :(得分: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 {
    }
}

但是以下语句将返回null:

// this always returns null
Baz baz = Foo.class.getAnnotation(Baz.class)

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