自定義Annotation

來源:http://blog.csdn.net/lifetragedy/article/details/7394910java

概念篇

來看一個最簡單的annotation示例面試

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1
{
    String value();
}
  1. Annotation須要聲明爲@interface這樣的東西
  2. @Target(ElementType.TYPE)表明這個annotation必須且必定要加在什麼樣的語句上面,例如
    ElementType.TYPE表明此Annotation必須聲明在public class Student{…}的上面,而不能寫在任何的method{}(方法)或者是field(屬性)的上方。
    • @Target: 表示該註解能夠用於什麼地方。可用ElementType枚舉類型主要有:
      • TYPE : 類、接口或enum聲明
      • FIELD: 域(屬性)聲明
      • METHOD: 方法聲明
      • PARAMETER: 參數聲明
      • CONSTRUCTOR: 構造方法聲明
      • LOCAL_VARIABLE:局部變量聲明
      • ANNOTATION_TYPE:註釋類型聲明
      • PACKAGE: 包聲明
  3. Retention若是設爲了RUNTIME,表明此annotation的具體實現能夠在運行時用類反射來實現
    咱們看到了,annotation通常爲一個@interface,也沒啥具體的implementation(實現)
    怎麼實現這個annotation呢?類反射。
    • @Retention: 表示須要在什麼級別保存該註解信息。可用RetentionPolicy枚舉類型主要有:
      • SOURCE: 註解將被編譯器丟棄。
      • CLASS: 註解在class文件中可能。但會被VM丟棄。
      • RUNTIME: VM將在運行時也保存註解(若是須要經過反射讀取註解,則
        使用該值)。
  4. @Documented: 將此註解包含在Javadoc中。

上面這個MyAnnotation1.class文件包含一個值,下面來一個含有兩個值的annotation數據庫

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2
{
    String description();
    boolean isAnnotation();
}

關鍵是來看這兩個自定義annotation的用法:數據結構

@MyAnnotation1("this isannotation1")
public class AnnotationDemo
{
    @MyAnnotation2(description = "this is annotation2", isAnnotation = true)
    public void sayHello()
    {
        System.out.println("hello world!");
    }
    
    public static void main(String[] args)
    {
        new AnnotationDemo().sayHello();
    }
}

若是把@MyAnnotation1與@MyAnnotation2的位置換一換,會怎麼樣?
eclipse會報The annotation @MyAnnotation2 is disallowed for this locationeclipse

高級篇

首先,網上的一些關於自定義annotation教程所舉的例子都不太好!this

就2個例子,而後一幫子人在那邊處處COPY這兩個例子而後處處轉發,搞得來你們雲裏霧裏一頭霧水, 同時一羣企業的面試官也就喜歡拿這個自定義annotation來做面試題,好像會個annotation就能給Senior software engineer了。.net

其實Annotation就是類反射加點枚舉,比個數據結構裏的冒泡排序還簡單,沒這麼誇張,關鍵是例子舉的很差,如今來看看下面這個例子。code

經過例子來看一個簡單的Annotation

Hibernate的機制是可能經過JAVA類而後逆向成數據庫裏的某個表,你們還記得吧?
好比說Student.java文件,若是你這樣寫:blog

@Table(name="T_STUDENT")
Public class Student{…}

表明這個類對應的數據庫表叫T_STUDENT排序

public class Student
{
    private String  id  = "";

    @Id(init = 1)
    public void setId(String id)
    {
        this.id = id;
    }
}

就表明id這個field是一個主鍵,它的初始值爲1。
好了,如今開始咱們本身的例子,設有一CLASS叫Student,其中有三個fields:

private String name = "";
private int age = 0;
private String studentId = "";

相應的每個field有一對的set, get方法

而後我在每一個set方法上造一個annotation叫ValueBind的註解,其做用是:
只要set方法上帶有ValueBind註解,它就會根據這個字段的類型把一個默認值,自動賦給Student類中相對應的field。
先來看一下Student類:

public class Student
{
    private String name = "";
    private int age = 0;
    private String studentId = "";
    public String getName()
    {
        return name;
    }
    @ValueBind(type=fieldType.STRING, value="aa")
    public void setName(String name)
    {
        this.name = name;
    }
    public int getAge()
    {
        return age;
    }
    @ValueBind(type=fieldType.INT, value="11")
    public void setAge(int age)
    {
        this.age = age;
    }
    public String getStudentId()
    {
        return studentId;
    }
    @ValueBind(type=fieldType.STRING, value="1")
    public void setStudentId(String studentId)
    {
        this.studentId = studentId;
    }
}

自定義一個ValueBind的Annotation,這個@ValueBoind就是個人自定義的annotation,裏面有兩個值,來看這個annotation是怎麼作的吧:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValueBind
{
    enum fieldType{
        STRING, INT
    }
    
    fieldType type();
    String value();
}

夠簡單的吧!
首先這個annotation只能被標註在方法上
其次它含有兩個值,一個是enum類型,一個是String類型

利用JAVA類反射來實現咱們的Annotation

如今來看咱們真正的實現(用類反射來實現)

public class PersistStudent
{
    public static void main(String[] args) throws Exception
    {
        Object c = Class.forName("annotation.Student").newInstance();
        try
        {
            Method[] methodArray = c.getClass().getDeclaredMethods();
            for (int i = 0; i < methodArray.length; i++)
            {
                if (methodArray[i].isAnnotationPresent(ValueBind.class))
                {
                    ValueBind annotation = methodArray[i].getAnnotation(ValueBind.class);
                    String type = String.valueOf(annotation.type());
                    String value = annotation.value();
                    if (type.equals("INT"))
                    {
                        methodArray[i].invoke(c, new Object[] { new Integer(value) });
                    }
                    else
                    {
                        methodArray[i].invoke(c, new Object[] { value });
                    }
                }
            }
            Student annotaedStudent = (Student) c;
            System.out.println("studentId====" + annotaedStudent.getStudentId() + "  studentnName====" + annotaedStudent.getName() + "   student Age====" + annotaedStudent.getAge());
        }
        catch (Exception e)
        {
            throw new Exception(e);
        }
    }
}

運行完畢後顯示:
studentId == 1 studentnName == aa student Age ==11

本身把代碼敲到eclipse裏後再去感覺一下吧,立刻讓你annotation入門

相關文章
相關標籤/搜索