Java學習:Annotation註解

Annotation不算經常使用的技術,早前用它寫了一些玩意兒,過了一年又忘乾淨了,今天寫點東西記下來,以備再忘之需。java

 

java.lang.annotation,接口 Annotation。對於Annotation,是Java5的新特性,JDK5引入了Metedata(元數據)很容易的就可以調用Annotations。Annotations提供一些原本不屬於程序的數據,好比:一段代碼的做者或者告訴編譯器禁止一些特殊的錯誤。An annotation 對代碼的執行沒有什麼影響。Annotations使用@annotation的形式應用於代碼:類(class),屬性(attribute),方法(method)等等。一個Annotation出如今上面提到的開始位置,並且通常只有一行,也能夠包含有任意的參數。數組

 

——————百度百科dom

 

Annotation是什麼,上面說得很清楚了,下面重點說,它怎麼寫,和有什麼用。ide

 1、Annotation的基本寫法this

/**
 * @author caiyu
 * @date 2014-1-21
 */

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSchemaConfig {
    String type() default "get";
    String value();
}

 

一、DataSchemaConfig爲Annotation的名稱spa

二、 @Retention 表示該Annotation的保留級別code

分別如下三種:htm

RetentionPolicy.RUNTIMEblog

會記錄在CLASS裏,同時會在運行時保留該註解,以使其能夠被反射讀取。接口

RetentionPolicy.SOURCE

只存在於源碼裏,會被編譯器拋棄

RetentionPolicy.CLASS

會被編譯器記錄在CLASS文件中,但虛擬機不會在運行時保留它。該選項是默認選項

三、@Target表示該Annotation的影響範圍,以下所示:

package java.lang.annotation;

/**
 * A program element type.  The constants of this enumerated type
 * provide a simple classification of the declared elements in a
 * Java program.
 *
 * <p>These constants are used with the {@link Target} meta-annotation type
 * to specify where it is legal to use an annotation type.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE
}

 

四、內容組織形式

String type() default "get";

 這段聲明裏,String爲成員類型,type爲成員名稱(必須寫上括號),default "get"表示缺省指爲"get"

 

五、使用見以下示例代碼

  

/**
 * @author caiyu
 * @date 2014-1-22
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DataType {
    public String value() default "map";
}



@DataType(value = "bean")
public class MapModel {
    private Map<String, Object> o = new HashMap<String, Object>();

    @GET
    public Object get(String key) {
        return o.get(key);
    }

    @PUT
    public void put(String key, Object value) {
        o.put(key, value);
    }
}

 

DataType 這個Annotation被聲明爲Runtime以及TYPE,因此它能夠被用於註解MapModel這個類。
括號裏的value="bean",則是爲其value賦值1,同時因爲value是個特殊成員,能夠寫做
@DataType("bean")

  若是寫做

@DataType

  則value會使用默認值"map"

 

六、數組形式的成員類型的使用

 把上面的內容改爲下面的格式:

String[] value() default "map";

以前的這種寫法@DataType("bean")仍然是合法的

  同時能夠寫做@DataType({"map","bean"})

 

 

 2、Annotaion的用途

在介紹@Retention的時候,其實已經說明了Annotation的三種類型了,SOURCE和CLASS類型使用不多,若是你不是須要本身寫一個Java Compiler或者Editor,基本用不上。

這裏重點說說RUNTIME類型。

咱們知道,RUNTIME會被保存在CLASS文件中,並且其中記錄的信息能夠經過反射來獲取到,因而能夠利用這點實現一些方便的配置(好比Spring和Hibernate就是利用這點)。

 來看看一個MapModel類:

@DataType
public class MapModel {
    private Map<String, Object> o = new HashMap<String, Object>();

    @get
    public Object getProperty(String key) {
        return o.get(key);
    }

    @put
    public void putProperty(String key, Object value) {
        o.put(key, value);
    }

    public String toString() {
        return o.toString();
    }
}

 

能夠看到,MapModel標記了三個註解,分別是DataType和get、put

下面的代碼,是用來把該Model和org.dom4j.Element相互轉換的,注意只能參考,並不完整:

/**
     * 序列化註解類型
     * 
     * @param content
     * @param schema
     * @return
     */
    private Element serialMapType(Object content, IDataSchema<?> schema) {
        DataType type = schema.getType().getAnnotation(DataType.class);
        if (type != null && type.value() == DataTypeValue.MAP) {
            Element root = DocumentFactory.getInstance().createElement(
                    schema.getName());

            Method getMethod = extraMethodByAnnotation(schema.getType(),
                    get.class);
            if (getMethod == null)
                throw new InvalidAnnotationConfigException(
                        "Invalid annotation class: "
                                + schema.getType().getName());
            try {
                for (Entry<String, IDataSchema<?>> field : schema
                        .getFieldEntrySet()) {
                    Object o = getMethod.invoke(content, field.getValue()
                            .getId());
                    Element e = save(o, field.getValue());
                    root.add(e);
                }
                return root;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                throw new InvalidAnnotationConfigException(
                        "Invalid put method : " + getMethod.getName());
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }

        return null;
    }



    /**
     * 反序列化註解類型數據
     * 
     * @param persistentTarget
     * @param schema
     * @return
     */
    private Object deserialMapType(Element persistentTarget,
            IDataSchema<?> schema) {
        Object instance = null;
        DataType type = schema.getType().getAnnotation(DataType.class);
        if (type != null && type.value() == DataTypeValue.MAP) {
            Method putMethod = extraMethodByAnnotation(schema.getType(),
                    put.class);
            if (putMethod == null)
                throw new InvalidAnnotationConfigException(
                        "Invalid annotation class: "
                                + schema.getType().getName());
            try {
                instance = schema.getType().newInstance();
                for (Entry<String, IDataSchema<?>> field : schema
                        .getFieldEntrySet()) {
                    Element e = persistentTarget.element(field.getValue()
                            .getName());
                    Object v = load(e, field.getValue());
                    putMethod.invoke(instance, new Object[] {
                            field.getValue().getId(), v });
                }
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                throw new InvalidAnnotationConfigException(
                        "Invalid put method : " + putMethod.getName());
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return instance;
    }

 

 

    /**
     * 抽取含有指定註解的方法
     * 
     * @param type
     * @param annotationClass
     * @return
     */
    private Method extraMethodByAnnotation(Class<?> type,
            Class<? extends Annotation> annotationClass) {
        for (Method method : type.getDeclaredMethods()) {
            Annotation t = method.getAnnotation(annotationClass);
            if (t != null) {
                return method;
            }

        }
        return null;
    }
相關文章
相關標籤/搜索