2013-08-12 32 views
61

Ai đó có thể giải thích cho tôi cách chú thích hoạt động nội bộ trong java?Làm cách nào để chú thích hoạt động trong nội bộ

Tôi biết cách chúng tôi có thể tạo chú thích tùy chỉnh bằng cách sử dụng thư viện java.lang.annotation trong java. Nhưng tôi vẫn không hiểu đủ về cách nó hoạt động bên trong như chú thích @Override.

Tôi thực sự biết ơn nếu có ai đó giải thích chi tiết.

+2

Ý anh là gì bằng cách "làm việc trong nội bộ"? Trình biên dịch? Thời gian chạy? – chrylis

+0

@chrylis Làm việc nội bộ có nghĩa là cách nó tự động xác định rằng phương pháp này là phương pháp ghi đè hoặc phương pháp này không phải là phương pháp ghi đè. Nó hoạt động trên cả hai thời gian. giống như ghi đè chú thích làm việc trong thời gian biên dịch và chú thích bộ điều khiển lò xo hoạt động trong thời gian chạy –

Trả lời

94

Sự khác biệt chính đầu tiên giữa các loại chú thích là chúng được sử dụng tại thời gian biên dịch và sau đó bị loại bỏ (như @Override) hoặc được đặt trong tệp lớp đã biên dịch và có sẵn khi chạy (như Spring @Component). Điều này được xác định bởi chính sách @Retention của chú thích. Nếu bạn đang viết chú thích của riêng mình, bạn cần quyết định xem chú thích có hữu ích khi chạy (để tự động định cấu hình, có thể) hay chỉ ở thời gian biên dịch (để kiểm tra hoặc tạo mã).

Khi biên dịch mã bằng chú thích, trình biên dịch thấy chú thích giống như nó thấy các công cụ sửa đổi khác trên các phần tử nguồn, như công cụ sửa đổi truy cập (public/private) hoặc final. Khi nó gặp một chú thích, nó chạy một bộ xử lý chú thích, giống như một trình cắm thêm cho biết nó quan tâm đến một chú thích cụ thể. Bộ xử lý chú thích thường sử dụng API phản chiếu để kiểm tra các phần tử được biên dịch và có thể chỉ cần chạy kiểm tra trên chúng, sửa đổi chúng hoặc tạo mã mới để được biên dịch. @Override là một ví dụ đầu tiên; nó sử dụng API phản chiếu để đảm bảo rằng nó có thể tìm thấy một kết quả phù hợp cho chữ ký phương thức trong một trong các siêu lớp và sử dụng Messager để gây ra lỗi biên dịch nếu không thể.

Có một số hướng dẫn có sẵn để viết bộ xử lý chú thích; here's a useful one. Xem qua các phương thức trên the Processor interface để biết trình biên dịch gọi trình xử lý chú thích như thế nào; hoạt động chính diễn ra theo phương thức process, được gọi mỗi khi trình biên dịch thấy một phần tử có chú thích phù hợp.

+0

Cảm ơn @chrylis bây giờ tôi rõ ràng tất cả các nghi ngờ của tôi về Annotation. –

+2

sẽ rất hay khi chỉ cho chúng tôi biết cách trình xử lý chú thích của Spring phân tích cú pháp @Component và đưa lớp vào trong vùng chứa của nó –

+0

@shanyangqu Đó là chủ đề không phù hợp với câu hỏi. Bạn có thể tự đọc các lớp sau xử lý. – chrylis

5

Đây là @Override: http://www.docjar.com/html/api/java/lang/Override.java.html.

Không có gì đặc biệt về việc phân biệt nó với chú thích mà bạn có thể tự viết. Các bit thú vị nằm trong số người tiêu dùng của các chú thích. Đối với một chú thích như @Override, sẽ có trong trình biên dịch Java, hoặc một công cụ phân tích mã tĩnh hoặc IDE của bạn.

+1

Tôi biết rằng mã nguồn của ghi chú Ghi đè. Nhưng nó hoạt động như thế nào trong nội bộ. như cách nó có thể được xác định phương pháp này không phải là phương pháp ghi đè hoặc phương pháp này là ghi đè lên? hoặc tôi có thể tạo chú thích ghi đè tùy chỉnh của mình không? và nó phải hoạt động chính xác giống như hành vi như chú thích ghi đè java –

+2

Như tôi đã nói trong câu trả lời của tôi, ** hành vi không phải là một phần của chú thích. ** Cách giải thích nằm trong những thứ tiêu thụ chú thích. Do đó, trừ khi bạn thay đổi người tiêu dùng, bạn không thể tạo phiên bản tùy chỉnh '@ Ghi đè' của riêng mình (hoặc các chú thích chuẩn khác). –

3

Làm theo link này. Điều này sẽ cung cấp câu trả lời gần cho vấn đề của bạn. Nếu chúng tôi tập trung vào chú thích trong Java, Chú thích đã được giới thiệu trong Java 5 và không phải là Mùa xuân cụ thể. Nói chung, chú thích cho phép bạn thêm siêu dữ liệu vào một lớp, phương thức hoặc biến. Một chú thích có thể được biên dịch bởi trình biên dịch (ví dụ, chú thích @Override) hoặc bởi một khung công tác chẳng hạn như spring (ví dụ, chú thích @Component).

Ngoài ra tôi đang thêm nhiều tham chiếu hơn.

  1. http://www.codeproject.com/Articles/272736/Understanding-Annotations-in-Java
  2. http://docs.oracle.com/javase/7/docs/api/java/lang/annotation/package-summary.html
  3. http://www.coderanch.com/how-to/java/AnnotationsExample
+0

@LuiggiMendoza java 1.7 chú thích doc thêm –

+0

@Ruchira tôi đã được mở tất cả các liên kết nhưng tôi vẫn không xóa cách hoạt động của nó. Bạn có thể giải thích cho tôi chi tiết như coi là chú thích mùa xuân không. Tôi có thể làm tất cả mọi thứ bằng cách sử dụng chú thích mà không cần viết bất kỳ cấu hình nào trong tệp spring.xml. là nó liên kết nội bộ chú thích với cấu hình xml? –

+0

@ChiragDasani hãy xem xét điều này. điều này có thể giúp bạn http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s11.html và cũng xem bài đăng SO này http://stackoverflow.com/questions/2798181/ những gì-là-chú thích-và-như-làm-họ-thực sự-làm việc-cho-khuôn khổ-như-mùa xuân –

2

Về cơ bản, chú thích chỉ là dấu hiệu được đọc bởi trình biên dịch hoặc ứng dụng. Tùy thuộc vào chính sách lưu giữ của chúng, chúng chỉ có sẵn ở thời gian biên dịch hoặc có thể đọc được khi chạy bằng phản xạ.

Nhiều khung công cụ sử dụng lưu giữ thời gian chạy, nghĩa là họ kiểm tra một cách phản chiếu xem một số chú thích có xuất hiện trên lớp, phương pháp, trường v.v. và thực hiện điều gì đó nếu chú thích hiện diện (hay không). Ngoài ra, các thành viên của chú thích có thể được sử dụng để truyền thông tin thêm.

19

Bên cạnh những gì người khác đề xuất, tôi khuyên bạn nên viết chú thích tùy chỉnh và bộ xử lý của nó từ đầu để xem chú thích hoạt động như thế nào.

Ví dụ, tôi đã viết chú thích để kiểm tra xem các phương thức có bị quá tải trong thời gian biên dịch hay không.

Trước hết, hãy tạo chú thích có tên Overload. chú thích này được áp dụng cho phương pháp vì vậy tôi chú thích nó với @Target(value=ElementType.METHOD)

package gearon.customAnnotation; 

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

@Target(value=ElementType.METHOD) 
public @interface Overload { 

} 

Tiếp theo, tạo bộ vi xử lý tương ứng để xử lý các yếu tố chú thích bằng cách chú thích định nghĩa. Đối với phương thức được chú thích bởi @Overload, chữ ký của nó phải xuất hiện nhiều lần. Hoặc lỗi được in.

package gearon.customAnnotation; 

import java.util.HashMap; 
import java.util.Map.Entry; 
import java.util.Set; 

import javax.annotation.processing.AbstractProcessor; 
import javax.annotation.processing.RoundEnvironment; 
import javax.annotation.processing.SupportedAnnotationTypes; 
import javax.lang.model.element.Element; 
import javax.lang.model.element.TypeElement; 
import javax.tools.Diagnostic.Kind; 

@SupportedAnnotationTypes("gearon.customAnnotation.Overload") 

public class OverloadProcessor extends AbstractProcessor{ 

    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
     // TODO Auto-generated method stub 
     HashMap<String, Integer> map = new HashMap<String, Integer>(); 

     for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){ 
      String signature = element.getSimpleName().toString(); 
      int count = map.containsKey(signature) ? map.get(signature) : 0; 
      map.put(signature, ++count); 
     } 

     for(Entry<String, Integer> entry: map.entrySet()){ 
      if(entry.getValue() == 1){ 
       processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() + " has not been overloaded"); 
      } 
     } 
     return true; 
    } 
} 

Sau khi đóng gói chú thích và quy trình vào tệp jar, hãy tạo lớp học với @Overload và sử dụng javac.exe để biên dịch nó.

import gearon.customAnnotation.Overload; 

public class OverloadTest { 
    @Overload 
    public static void foo(){ 
    } 

    @Overload 
    public static void foo(String s){ 

    } 

    @Overload 
    public static void nonOverloadedMethod(){ 

    } 
} 

Kể từ nonOverloadedMethod() chưa thực sự được quá tải, chúng tôi sẽ nhận được đầu ra như dưới đây:

enter image description here

+0

Thông tin trên là rất tôn trọng JDK6 (+1 cho điều đó), nhưng làm thế nào để đạt được điều tương tự bằng cách sử dụng JDK5 là tốt?Sử dụng JDK6 SupportedAnnotationTypes, lớp AbstractProcessor nó trở nên đơn giản hơn nhưng làm thế nào điều tương tự đã xảy ra trong quá khứ (như Spring FrameWork 2.5 trên jdk5)? Làm thế nào JVM phát hiện bộ xử lý chú thích như lớp trong jdk5? bạn có thể vui lòng hướng dẫn bằng cách chỉnh sửa câu trả lời trong 2 phần (một cho JDK5, Phiên bản hiện tại là dành cho Jdk6 +)? – RawAliasCoder

+0

ví dụ rất hay –