天天看點

注解(Annotation)--注解處理器

如果沒有用來讀取注解的方法和工作,那麼注解也就不會比注釋更有用處了。使用注解的過程中,很重要的一部分就是建立于使用注解處理器。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():傳回直接存在于此元素上的所有注釋。與此接口中的其他方法不同,該方法将忽略繼承的注釋。(如果沒有注釋直接存在于此元素上,則傳回長度為零的一個數組。)該方法的調用者可以随意修改傳回的數組;這不會對其他調用者傳回的數組産生任何影響。

  一個簡單的注解處理器:  

注解(Annotation)--注解處理器
/***********注解聲明***************/

/**
 * 水果名稱注解
 * @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号紅富士大廈      
注解(Annotation)--注解處理器

   Java注解的基礎知識點(見下面導圖)基本都過了一遍,下一篇我們通過設計一個基于注解的簡單的ORM架構,來綜合應用和進一步加深對注解的各個知識點的了解和運用。

注解(Annotation)--注解處理器