2011-10-07 40 views
35

Tôi có một chú thích tùy chỉnh được gọi @Pojo mà tôi sử dụng cho tự động thế hệ tài liệu wiki:Java xử lý 6 chú thích - nhận được một lớp từ chú thích

package com.example.annotations; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.SOURCE) 
@Target(ElementType.METHOD) 
public @interface Pojo { 
    Class<?> value(); 
} 

tôi sử dụng nó như thế này:

@Pojo(com.example.restserver.model.appointment.Appointment.class) 

để chú thích phương thức tài nguyên để bộ xử lý chú thích có thể tự động tạo trang wiki mô tả tài nguyên và loại mà nó mong đợi.

Tôi cần đọc giá trị của trường value trong bộ xử lý chú thích, nhưng tôi gặp phải lỗi thời gian chạy.

Trong mã nguồn cho bộ xử lý của tôi, tôi có những dòng sau:

final Pojo pojo = element.getAnnotation(Pojo.class); 
// ... 
final Class<?> pojoJavaClass = pojo.value(); 

nhưng lớp thực tế trong không dành cho bộ vi xử lý. Tôi nghĩ tôi cần một số javax.lang.model.type.TypeMirror để thay thế cho lớp học thực sự. Tôi không chắc chắn làm thế nào để có được một.

Các lỗi tôi nhận được là:

javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror com.example.restserver.model.appointment.Appointment 

Các Appointment là một lớp học đề cập trong một trong @Pojo chú thích của tôi.

Thật không may, tài liệu và/hoặc hướng dẫn về xử lý chú thích Java có vẻ khan hiếm. Đã thử googling.

+1

Không nhiều người hỏi loại câu hỏi này, nhưng đối với những người trong chúng ta sống ở Tartarus (Java), sự hỗ trợ của những người khác trở nên rất hữu ích – Ordiel

Trả lời

20

Bạn đã đọc bài viết này: http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/?

Bí quyết là sử dụng getAnnotation() và bắt MirroredTypeException. Đáng ngạc nhiên là ngoại lệ sau đó cung cấp TypeMirror của lớp được yêu cầu.

Tôi không biết đây có phải là giải pháp hay không, nhưng đó là một giải pháp. Theo ý kiến ​​cá nhân của tôi, tôi sẽ cố gắng để có được loại đằng sau các MirroredType, nhưng tôi không biết nếu điều này là có thể.

+1

Điều đó có thể thực hiện thủ thuật, mặc dù "băng keo và kẹo cao su" đến với ý nghĩ. BTW, tên người dùng tuyệt vời :-). – Ralph

32

Tôi đến đây để hỏi câu hỏi tương tự EXACT. ... và tìm thấy cùng một blog link được đăng bởi Ralph.

Đó là một bài viết dài nhưng rất phong phú. Tóm tắt câu chuyện - có hai cách để làm điều đó, cách dễ dàng và cách "đúng hơn".

Đây là cách dễ dàng:

private static TypeMirror getMyValue1(MyAnnotation annotation) { 
    try 
    { 
     annotation.myValue(); // this should throw 
    } 
    catch(MirroredTypeException mte) 
    { 
     return mte.getTypeMirror(); 
    } 
    return null; // can this ever happen ?? 
} 

Cách tẻ nhạt hơn khác (không có trường hợp ngoại lệ):

private static AnnotationMirror getAnnotationMirror(TypeElement typeElement, Class<?> clazz) { 
    String clazzName = clazz.getName(); 
    for(AnnotationMirror m : typeElement.getAnnotationMirrors()) { 
     if(m.getAnnotationType().toString().equals(clazzName)) { 
      return m; 
     } 
    } 
    return null; 
} 

private static AnnotationValue getAnnotationValue(AnnotationMirror annotationMirror, String key) { 
    for(Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) { 
     if(entry.getKey().getSimpleName().toString().equals(key)) { 
      return entry.getValue(); 
     } 
    } 
    return null; 
} 


public TypeMirror getMyValue2(TypeElement foo) { 
    AnnotationMirror am = getAnnotationMirror(foo, MyAnnotation.class); 
    if(am == null) { 
     return null; 
    } 
    AnnotationValue av = getAnnotationValue(am, "myValue"); 
    if(av == null) { 
     return null; 
    } else { 
     return (TypeMirror)av.getValue(); 
    } 
} 

Tất nhiên, một khi bạn có được một TypeMirror, bạn (ít nhất là trong kinh nghiệm của tôi) khá nhiều lúc nào cũng muốn có TypeElement thay thế:

private TypeElement asTypeElement(TypeMirror typeMirror) { 
    Types TypeUtils = this.processingEnv.getTypeUtils(); 
    return (TypeElement)TypeUtils.asElement(typeMirror); 
} 

... mà ít bit không rõ ràng cuối cùng đã cho tôi một giờ của tóc kéo trước khi tôi sắp xếp nó ra lần đầu tiên. Các bộ xử lý chú thích này thực sự không khó để viết gì cả, các API chỉ siêu khó hiểu ở lần đầu tiên và tiết lộ chi tiết.Tôi bị cám dỗ để đưa ra một lớp trợ giúp mà làm cho tất cả các hoạt động cơ bản rõ ràng ... nhưng đó là một câu chuyện cho một ngày khác (msg tôi nếu bạn muốn nó).

+0

Tôi cũng bị kẹt ở đây. Bạn có thể xuất bản một gist với helper của bạn nếu bạn đã làm bất kỳ, xin vui lòng? – gorodechnyj

+1

@gorodechnyj - đây là mã tôi đã viết vào thời điểm đó: https://github.com/ddopson/EpicFramework/blob/uiv2/EpicBuilder/src/com/epic/framework/build/EpicAnnotationProcessor.java Hãy thoải mái tìm hiểu nó và ăn cắp tự do. –

Các vấn đề liên quan