Annotation

在spring、hibernate等流行的開源框架中,基本上來進行配置的方式有兩種,一種是基於配置文件的配置,注入applicationContext.xml或者是hbm.xml,一樣另外一種方式則是基於註解的配置,能夠說使用註解的配置至關的簡潔明瞭,因此這裏就再來回顧一下什麼是Annotation。java

1、Annotation基本概念spring

Annotation是jdk5之後出現的新特性,在jdk中,其內置了許多本身的Annotation,例如@Override,@SuppresWarning,@Deprecated等等,其中一些Annotation是標誌性的Annotation,例如@Override就是表示這個類要重寫父類的方法。數組

咱們首先要清楚的知道一點,其實Annotation和Class、Interface這些同樣,都是類級別的,並且咱們建立的每個Annotation都默認的繼承了java.lang.annotation.Annotation這個接口,注意:若是一個接口繼承了這個Annotation接口,那麼這個接口並非一個Annotationapp

咱們接下來本身建立一個簡單的Annotation:框架

public @interface MyAnnotation
{
    String value();
    String name() default "xiaoluo";
}

這樣就定義了咱們本身的一個Annotation了,它的標識符就是  @interface,一樣,Annotation裏面能夠定義咱們的屬性,例如,上面的例子我就定義了兩個String類型的屬性,一個是value屬性,一個是name屬性,注意:在Annotation裏定義屬性,屬性後面都要加上括號。同時咱們還能夠給Annotation的屬性設置默認值,經過 default 這個關鍵字來設置默認值,接下來咱們就可使用咱們本身定義的Annotation了:ide

@MyAnnotation(value="hello", name="world")
public class AnnotationTest
{
    @MyAnnotation("xiaoluo")
    public void hello()
    {
        System.out.println("This is my Annotation!");
    }
}

咱們看到,這個時候咱們就能夠在類上面、方法上面使用咱們的Annotation了,注意:在本身定義的Annotation中,若是爲其設置了屬性,則咱們必需要給其屬性賦值函數

在上面的例子中,咱們看到 @MyAnnotation(value="hello", name="world") 這裏就是給其 value屬性和name 屬性賦值,而在下面的那個Annotation中:spa

@MyAnnotation("xiaoluo"),咱們沒有指定其屬性名,那麼它是賦值給誰呢?在Annotation中,若是咱們定義了一個 value 屬性,那麼咱們在使用該Annotation,給其賦值時,能夠不用寫出屬性的名字,即valuehibernate

怎麼樣,簡單吧,這樣咱們就定義並使用了咱們的Annotation了。code

2、Retention和RetentionPolicy

在初步瞭解了Annotation以後,咱們再來看看Retention和RetentionPolicy這兩個概念,Retention的中文意思是,保留、持有,一樣,Retention也是一個Annotation,經過這個註解,咱們能夠指定咱們本身定義的Annotation的保留範圍,其默認值是有三個,是枚舉類型的值,RetentionPolicy.CLASS(這個是Retention的默認值,表示這個Annotation會被編譯到class文件當中), RetentionPolicy.RESOURCE(這個表示Annotation僅僅在編譯的時候有效,起到提示做用,並不會被編譯到class文件當中去), RetentionPolicy.RUNTIME(這個表示Annotation不只會被編譯到class文件當中,並且會在JVM運行中也能夠獲得這個Annotation,這樣咱們就能夠經過反射來獲得Annotaion,並對其進行一些操做了),咱們來看看jdk自帶的一些Annotation,其Retention分別是什麼:

@Retention(value=SOURCE)
public @interface Override

@Retention(value=SOURCE)
public @interface SuppressWarnings

@Retention(value=RUNTIME)
public @interface Deprecated

咱們看到,Deprecated的RetentionPolicy是RUNTIME的,這樣咱們能夠經過反射在運行時獲得其Annotation,接下來咱們本身來指定咱們剛定義的MyAnnotation爲RUNTIME:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
    String value();
    String name() default "xiaoluo";
}

這個時候,咱們定義的Annotation就會被編譯到class文件當中去,而且在運行時能夠獲得它,接下來咱們來經過一個例子來看看如何使用反射機制獲得咱們的Annotation以及咱們設置的屬性值,java的API指定了訪問獲得Annotation的方法,咱們的Class,Method,Constructor等等這些都默認實現了 AnnotatedElement 這個接口,這個接口定義了四個經常使用的方法:

<T extends Annotation> T  getAnnotation(Class<T> annotationClass)    // 根據Annotation.class獲得這個Annotation

Annotation[] getAnnotations()    //  獲得一個Annotation數組

Annotation[] getDeclaredAnnotations()  //  也是獲得一個Annotation數組

boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)    //  判斷是否爲被當前的Annotation所標識
@MyAnnotation("hello")
public class AnnotationTest
{
    @MyAnnotation(value="xiaoluo", name="welcome")
    public void hello()
    {
        System.out.println("This is my Annotation!");
    }
    
    public static void main(String[] args) throws Exception
    {
        //    獲得AnnotationTest這個類的 class 對象
        Class<AnnotationTest> clazz = AnnotationTest.class;
        
        //    獲得AnnotationTest的一個實例對象
        AnnotationTest test = (AnnotationTest)clazz.newInstance();
        
        //    獲得方法名爲hello的Method對象
        Method method = clazz.getMethod("hello", new Class[]{});
    
        //    判斷hello這個方法是否被MyAnnotation這個註解所標記
        if(method.isAnnotationPresent(MyAnnotation.class))
        {
            //    獲得咱們的MyAnnotation這個註解
            MyAnnotation myAnnotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
            
            System.out.println(myAnnotation.name() + ", " + myAnnotation.value());
            
            method.invoke(test, new Object[]{});
        }
    }
}

咱們來看看,由於咱們的@MyAnnotation設置了其RetentionPolicy爲RUNTIME,因此咱們能夠在經過反射在運行時獲得該Annotation對象,結果輸出爲:

welcome, xiaoluo
This is my Annotation!

經過這個例子,我想你們應該知道了RecentPolicy的三個值的含義了吧,咱們均可以設置其爲RUNTIME,這樣就能夠在運行時對其進行判斷來處理咱們的業務邏輯了

3、Target和ElementType

最後咱們來看看Target和ElementType這兩個東東,Target這個也是一個註解,這個Annotation是用來指定咱們的Annotation能夠標誌的範圍,例如定義在類上,定義在方法上等等,其value就是經過ElementType來指定的,咱們來看看ElementType有哪些值:

ANNOTATION_TYPE     // 能夠定義在Annotation上

CONSTRUCTOR         // 能夠定義在構造函數上

FIELD          // 能夠定義屬性上

LOCAL_VARIABLE    // 能夠定義在方法的局部變量上

METHOD         // 能夠定義在方法上

PACKAGE        // 能夠定義在包上
  
PARAMETER       // 能夠定義在方法的參數上

TYPE         // 能夠定義在類上、接口上

咱們也能夠在剛纔定義的MyAnnotation上設置咱們的Target:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
    String value();
    String name() default "xiaoluo";
}

表示MyAnnotation能夠定義在類上還有方法上,若是在其餘地方定義該註解,則會編譯不經過

好了,Annotation的知識基本就是這些了,主要講解了Annotation的基本概念以及其的一些特性

相關文章
相關標籤/搜索