如果沒有用來讀取注解的方法和工作,那麼注解也就不會比注釋更有用處了。使用注解的過程中, 很重要的一部分就是創建於使用注解處理器。Java SE5擴展了反射機制的API,以幫助程序員快速的構 造自定義注解處理器。
注解處理器類庫(java.lang.reflect.AnnotatedElement):
Java 使用Annotation接口來代表程序元素前面的注解,該接口是所有Annotation類型的父接口。除此之外, Java在java.lang.reflect 包下新增了AnnotatedElement接口,該接口代表程序中可以接受注解的程序 元素,該接口主要有如下幾個實現類:
Class:類定義
Constructor:構造器定義
Field: 累的成員變量定義
Method:類的方法定義
Package:類的包定義
java.lang.reflect 包下 主要包含一些實現反射功能的工具類,實際上,java.lang.reflect 包所有提供的反射API擴充了讀取 運行時Annotation信息的能力。當一個Annotation類型被定義為運行時的Annotation後,該注解才能是 運行時可見,當class文件被裝載時被保存在class文件中的Annotation才會被虛擬機讀取。
AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通過 反射獲取了某個類的AnnotatedElement對象之後,程序就可以調用該對象的如下四個個方法來訪問 Annotation信息:
方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定類型的注解,如果該類型注解不存在,則返回null 。
方法2:Annotation[] getAnnotations():返回該程序元素上存在的所有注解。
方法3: boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判斷該程序 元素上是否包含指定類型的注解,存在則返回true,否則返回false.
方法4:Annotation[] getDeclaredAnnotations():返回直接存在於此元素上的所有注釋。與此接口中的其他方法不同,該方 法將忽略繼承的注釋。(如果沒有注釋直接存在於此元素上,則返回長度為零的一個數組。)該方法的 調用者可以隨意修改返回的數組;這不會對其他調用者返回的數組產生任何影響。
一個簡單的 注解處理器:
/***********注解聲明***************/ /** * 水果名稱注解 * @author peida * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitName { String value() default ""; } /** * 水果顏色注解 * @author peida * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitColor { /** * 顏色枚舉 * @author peida * */ public enum Color{ BULE,RED,GREEN}; /** * 顏色屬性 * @return */ Color fruitColor() default Color.GREEN; } /** * 水果供應者注解 * @author peida * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitProvider { /** * 供應商編號 * @return */ public int id() default -1; /** * 供應商名稱 * @return */ public String name() default ""; /** * 供應商地址 * @return */ public String address() default ""; } /***********注解使用***************/ public class Apple { @FruitName("Apple") private String appleName; @FruitColor(fruitColor=Color.RED) private String appleColor; @FruitProvider(id=1,name="陝西紅富士集團",address="陝西省西安市延安路89號紅富士大廈") private String appleProvider; public void setAppleColor(String appleColor) { this.appleColor = appleColor; } public String getAppleColor() { return appleColor; } public void setAppleName(String appleName) { this.appleName = appleName; } public String getAppleName() { return appleName; } public void setAppleProvider(String appleProvider) { this.appleProvider = appleProvider; } public String getAppleProvider() { return appleProvider; } public void displayName(){ System.out.println("水果的名字是:蘋果"); } } /***********注解處理器***************/ public class FruitInfoUtil { public static void getFruitInfo(Class<?> clazz){ String strFruitName=" 水果名稱:"; String strFruitColor=" 水果顏色:"; String strFruitProvicer="供應商信息:"; Field[] fields = clazz.getDeclaredFields(); for(Field field :fields){ if(field.isAnnotationPresent(FruitName.class)){ FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class); strFruitName=strFruitName+fruitName.value(); System.out.println(strFruitName); } else if(field.isAnnotationPresent(FruitColor.class)){ FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class); strFruitColor=strFruitColor+fruitColor.fruitColor().toString(); System.out.println(strFruitColor); } else if(field.isAnnotationPresent(FruitProvider.class)){ FruitProvider fruitProvider= (FruitProvider) field.getAnnotation (FruitProvider.class); strFruitProvicer=" 供應商編號:"+fruitProvider.id()+" 供應商名 稱:"+fruitProvider.name()+" 供應商地址:"+fruitProvider.address(); System.out.println(strFruitProvicer); } } } } /***********輸出結果***************/ public class FruitRun { /** * @param args */ public static void main(String[] args) { FruitInfoUtil.getFruitInfo(Apple.class); } } ==================================== 水果名稱:Apple 水果顏色:RED 供應商編號:1 供應商名稱:陝西紅富士集團 供應商地址:陝西省西安市延安路89號紅富士大廈
Java注解的基礎知識點(見下面導圖)基本都過了一遍,下一篇我們通過設計一個基於注解 的簡單的ORM框架,來綜合應用和進一步加深對注解的各個知識點的理解和運用。