5

Tôi đang cố gắng viết bộ xử lý Anntoation tùy chỉnh. Bộ xử lý chú thích sẽ xử lý từng tệp lớp tại thời gian biên dịch để kiểm tra chú thích, Nhưng làm thế nào để tôi có thể nhận được lớp mà nó hiện đang xử lý? Tôi chỉ có thể lấy tên lớp trong các mã sau đây.Bộ xử lý chú thích - Cách lấy Lớp đang xử lý

public class AnnotationProcessor extends AbstractProcessor { 
    ...... 
    @Override 
    public boolean process(Set<? extends TypeElement> annotations, 
     RoundEnvironment roundEnv) { 

    Set<? extends Element> rootE=roundEnv.getRootElements(); 
     for(Element e: rootE) { 
     if(e.getKind()==ElementKind.CLASS) { 
      String className= e.getSimpleName().toString(); 
      processingEnv.getMessager().printMessage(javax.tools.Diagnostic.Kind.WARNING,className, e); 
     } 
    } 
} 

Trả lời

7

Bạn không thể truy cập Lớp xử lý chú thích đang xử lý vì lớp chưa được biên soạn. Thay vào đó, Java cung cấp các phần tử tương tự api để kiểm tra kiểu phản chiếu của nguồn vào.

Yếu tố (bạn đã tìm thấy bằng cách sử dụng roundEnv.getRootElements()) có nhiều thông tin hơn về lớp đang được biên dịch chứ không chỉ tên của nó. Một tấn thông tin hữu ích có thể được tìm thấy bằng cách sử dụng các ElementVisitors:

http://docs.oracle.com/javase/6/docs/api/javax/lang/model/element/ElementVisitor.html http://docs.oracle.com/javase/6/docs/api/javax/lang/model/util/ElementKindVisitor6.html

Bao gồm các nhà xây dựng lớp học, phương pháp, các lĩnh vực, vv

Dưới đây là làm thế nào để sử dụng nó:

public class AnnotationProcessor extends AbstractProcessor { 
...... 
    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 

     Set<? extends Element> rootE=roundEnv.getRootElements(); 
     for(Element e: rootE) { 
      for(Element subElement : e.getEnclosedElements()){ 
       subElement.accept(new ExampleVisitor(), null); // implement ExampleVisitor 
      } 
     } 
    } 
} 
+0

Cảm ơn sự giúp đỡ của bạn: D – user1004413

+0

Bạn nói "... có nhiều thông tin hơn về lớp đang được biên dịch chứ không phải tên của nó", nhưng làm thế nào để _do_ bạn có được tên lớp? – Matthias

+0

Tên lớp sẽ có trong Element.getSimpleName() http://docs.oracle.com/javase/7/docs/api/javax/lang/model/element/Element.html#getSimpleName%28%29 –

3
  1. này không phải là cách hoạt động của tính năng AnnotationProcessing. Bạn không thể nhận được một đối tượng Class<?> trong khi xử lý vì các lớp mà bạn muốn định nghĩa của đang được biên dịch ngay NGAY BÂY GIỜ! Nếu bạn gọi số getClass() vào một lớp học không xác định hoặc sử dụng Class<?> clazz = Class.forName("com.your.fancy.Class"), bạn sẽ nhận được java.lang.ClassNotFoundException hoàn toàn ổn.
  2. Bạn cần sử dụng các lớp như javax.lang.model.element.Elementjavax.lang.model.element.ExecutableElement để mô tả/đọc định nghĩa lớp học của mình.
  3. Các javax.lang.model.*javax.lang.model.type.TypeMirror để mô tả các lớp học, các lĩnh vực của họ, phương pháp, vv
  4. Nếu bạn cần hiểu rõ hơn, chỉ bao gồm tools.jar từ trình biên dịch java (JAVA SDK) để có được định nghĩa kiểu hơn đó là được sử dụng trong quá trình biên dịch. Nhưng hầu hết có thể - bạn KHÔNG cần để thêm phụ thuộc jar này!
  5. Bạn sẽ nhận được ClassNotFoundException ngay cả sau roundEnvironment.processingOver()đúng.
  6. IN RÚT GỌN: SỬ DỤNG TypeMirror ở tất cả các nơi bạn muốn sử dụng loại Lớp.

Ví dụ:

  • get danh sách các phương pháp từ một lớp học:
tên phương pháp
public static @Nonnull List getMethods(@Nonnull Element annotationElem, @Nonnull RoundEnvironment roundEnvironment) { 
    List outList = new ArrayList(); 

    String simpleName = annotationElem.getSimpleName().toString(); 
    for (Element elem : roundEnvironment.getRootElements()) 
     if (elem.getSimpleName().toString().equals(simpleName)) 
      for (Element methodDeclaration :elem.getEnclosedElements()) 
       if (methodDeclaration instanceof ExecutableElement) 
        outList.add((ExecutableElement)methodDeclaration); 

    return outList; 
}
  • get từ phương pháp kê khai:
public static TypeMirror getMethodFirstParam(@Nonnull ExecutableElement method, int n) { 
    List parameters = ((ExecutableElement) method).getParameters(); 
    if (parameters != null && parameters.size() > 0) 
     return parameters.get(n).asType(); 
    return null; 
}
+0

chú thíchElem một phần tử gốc của roundEnvironment? – Sunnyday

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