在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接口,那麼這個接口並非一個Annotation。app
咱們接下來本身建立一個簡單的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,給其賦值時,能夠不用寫出屬性的名字,即value。hibernate
怎麼樣,簡單吧,這樣咱們就定義並使用了咱們的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的基本概念以及其的一些特性