2012-04-10 3 views
18

Nói rằng tôi có một chú thích với một tài sản:Đi qua thuộc tính chú thích để meta-chú thích

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

và tôi muốn tạo ra một chú thích hợp với một số meta-chú thích, bao gồm cả một trong đó có một tài sản

@Named 
@AnotherAnnotation 
@YetAnotherAnnotation 
public @interface CompoundAnnotation { 

    ... 
} 

Có cách nào để tôi có thể chuyển thuộc tính cho chú thích ghép vào một trong các chú thích meta không?

Ví dụ, một cái gì đó như thế này:

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

đó là tương đương, nhưng thuận tiện hơn nhiều so với

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

Cảm ơn!

Xin lỗi PS vì sự lựa chọn kém của tôi về chú thích mẫu - Tôi không có chú thích javax.inject. Chú thích được đặt tên trong đầu, chỉ một số chú thích tùy ý có thuộc tính.


Cảm ơn mọi người đã trả lời/nhận xét của bạn.

Có vẻ như trường hợp này không thể thực hiện được. Tuy nhiên, nó chỉ xảy ra rằng có một công việc đơn giản xung quanh cho trường hợp của tôi-in-điểm, mà tôi sẽ chia sẻ trong trường hợp nó giúp bất cứ ai:

Tôi đang làm việc với Spring và muốn tạo chú thích của riêng tôi có @ Thành phần dưới dạng chú giải meta, do đó được tự động phát hiện bằng quét thành phần. Tuy nhiên, tôi cũng muốn có thể thiết lập thuộc tính BeanName (tương ứng với thuộc tính value trong @Component) vì vậy tôi có thể có các tên bean tùy chỉnh. Vâng, nó chỉ ra rằng những người chu đáo tại Spring đã làm cho nó có thể làm điều đó - AnnotationBeanNameGenerator sẽ lấy thuộc tính 'value' của bất cứ chú thích nào được truyền và sử dụng nó như tên bean (và tất nhiên, bằng cách mặc định, nó sẽ chỉ nhận được chú thích được chuyển thành @Component hoặc có @Component dưới dạng chú giải meta). Nhìn lại điều này nên rõ ràng với tôi ngay từ đầu - đây là cách các chú thích hiện có với @Component như một chú thích meta, chẳng hạn như @Service và @Registry, có thể cung cấp tên bean.

Hy vọng điều đó hữu ích đối với ai đó. Tôi vẫn nghĩ rằng đó là một sự xấu hổ rằng điều này là không thể nói chung hơn mặc dù!

+0

Tôi không thấy như thế nào, trừ khi bạn đang thêm chú thích qua thao tác mã byte vào thời gian tải. (Hoặc một bộ xử lý chú thích tùy chỉnh, tôi giả sử.) Tò mò để xem tất cả những gì có thể là thủ thuật. –

+0

Chỉ cần suy nghĩ to ở đây, liệu đây có phải là cách giải quyết nếu bạn có một lớp cơ sở được chú thích với AnotherAnnotation và YAA, và sau đó lớp Person mở rộng không? Nhìn vào Reflections quá, có thể bạn sẽ nhận được một số ý tưởng: http://code.google.com/p/reflections/ – maksimov

+0

Liên quan đến http://stackoverflow.com/questions/1624084/why-is-not-possible- to-extend-annotations-in-java – Gray

Trả lời

6

Có cách nào để tôi có thể chuyển thuộc tính cho chú thích ghép vào một trong các chú thích meta không?

Tôi nghĩ câu trả lời đơn giản là "không". Không có cách nào để hỏi Person chú thích nào trên đó và nhận ví dụ @Named.

Câu trả lời phức tạp hơn là bạn có thể chuỗi chú thích nhưng bạn sẽ phải điều tra các chú thích này qua phản ánh.Ví dụ, các công việc sau:

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

Tuy nhiên, tuyên bố sau đây sẽ trả về null:

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

Điều này có nghĩa rằng bất kỳ lớp bên thứ 3 đó là tìm kiếm các @Baz chú thích sẽ không nhìn thấy nó.

14

Đó là một vài năm sau, và vì bạn đang sử dụng Spring, những gì bạn đang yêu cầu là có thể sử dụng chú thích @AliasFor.

Ví dụ:

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

Bây giờ bạn có thể chú thích thử nghiệm của bạn với @SpringContextTest(MyConfig.class), và điều tuyệt vời là nó thực sự hoạt động theo cách bạn mong đợi.