日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java基础-注解Annotation原理和用法

發布時間:2024/2/28 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java基础-注解Annotation原理和用法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自?http://www.wolfbe.com/detail/201608/265.html

在很多java代碼中都可以看到諸如@Override、@Deprecated、@SuppressWarnings這樣的字符,這些就是注解Annotation。注解最早在jdk5中被引入,現在已經成為java平臺很重要的一部分了,很多的框架程序中也喜歡使用注解,如Spring、Mybatis等。

那么,什么是注解呢?注解就是元數據,一種描述數據的數據,通俗一點就是為程序的元素(類、方法、成員變量)加上更直觀的說明,這些說明信息是與程序的業務邏輯無關的。但是,我們可以通過java的反射機制來獲取Annotation的信息,并根據這些信息來對程序進行賦值、分發等操作。
java5.0定義了4個標準的meta-annotation元注解,它們被用來提供對其它annotation類型作說明,四種元注解如下:
  • @Target;
  • @Retention;
  • @Inherited;
  • @Documented;

下面詳細說明這四種元注解的作用: @Target ? ? ?被用于描述注解的使用范圍,即注解可以用在所修飾對象的什么地方,取值可以是ElementType中的一種:
  • CONSTRUCTOR:用于描述構造器;
  • FIELD:用于描述域;
  • LOCAL_VARIABLE:用于描述局部變量;
  • METHOD:用于描述方法;
  • PACKAGE:用于描述包;
  • PARAMETER:用于描述參數;
  • TYPE:用于描述類、接口、注解類型或枚舉;

@Target(ElementType.TYPE)
public @interface Exculde{/*** 名稱,默認值為""* @return*/public String name() default "";}
@Target(ElementType.FIELD)public @interface Inject{/*** id,默認值為""* @return*/public String id() default "";
/*** 類,默認值為""* @return*/public Class?clazz() default Object.class;}
上面定義了兩個注解,注解@Exculde只能用于修飾類、接口、注解、枚舉,注解@Inject只能修飾類型的域,如:
@Exculde(name="admin")public class User{@Inject(id="username",clazz=String.class)private String username;}
@Retention ? ? ?用于描述注解的生命周期,即注解能在源碼到JVM裝載過程中的哪一個級別上有效。有些annotation僅出現在源碼中,被編譯器丟棄;有些annotation能被編譯進class文件中,可能被JVM忽略;有些annotation不但能夠被編譯進class文件,而且能夠在class文件被裝載時被讀取。這三種情況對應RetentionPoicy的三種取值:
  • SOURCE:源碼文件中保留;
  • CLASS:class文件中保留;
  • RUNTIME:運行時保留;

@Inherited ? ???用于描述注解是可以被繼承的,如果一個使用了@Inherited修飾的annotation被用于一個class,那么這個annotation也將被用于這個class的子類。@Inherited是一個標記注解,沒有參數選項,它修飾的annotation是被標記的class的子類所繼承,類并不從它所實現的接口繼承annotation,方法并不從它所重載的方法繼承annotation。 當使用java的反射去獲取一個@Inherited修飾的annotation時,反射檢查將遞歸檢查,檢查class和其父類,直到發現指定的annotation類型被發現,或者到達類繼承結構的頂層。
@Documented 用于描述注解信息應該被作為被標注的程序的公共API,即應該把注解信息保留文檔中。@Documented也是一個標記注解,沒有參數選項。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @interface Exculde{/*** 名稱注解,默認值為""* @return
? ? */public String name() default "";}
如果你看過了上面的元注解,如果還不能理解也沒關系,下面我們通過自定義注解來進一步理解元注解。
自定義注解需要使用@interface,類似于定義一個類使用class,但定義注解時不能再繼承其它的類或者接口,它已經自動繼承了java.lang.annotation.Annotation接口。@interface用來聲明一個注解,其中的每一個方法實際上聲明了一個配置參數,方法的名稱就是參數的名稱,方法的返回值類型就是參數的類型,也可以使用default來聲明參數的默認值。
定義注解的格式如下: public @interface 注解名{ 定義體 }
注解參數可支持的數據類型如下:
  • 基本類型;
  • Class;
  • String;
  • Enum;
  • Annotation;
  • 以上所有類型的數組形式;

下面定義一個類似于Spring的注解,用于向實例對象注入屬性的值:
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Inject{/*** ID,默認值為""* @return*/public String id() default "";
/*** 類,默認值為""* @return*/public Class?clazz() default Object.class;
}
把@Inject標注在類UserAction的屬性上:
public class UserAction {@Inject(id="userService",clazz=UserService.class)private UserService userService;}
在IOC容器框架中,對象都會被自動初始化,如果我們要實現IOC的這種功能,我們應該為加上@Inject注解的屬性userService注入它的值。首先我們應該通過反射獲取userService的域對象field,通過field獲取@Inject注解的信息,然后根據注解的id和clazz得到它依賴的值:
Inject inject = field.getAnnotation(Inject.class);String id = inject.id();Class?clazz = inject.clazz();
Object userService = Class.forName(clazz.getName).newInstance();field.setAccessible(true);field.set(object,userService);
上面代碼中,調用field.getAnnotation(Inject.class)獲取到@Inject的對象,然后獲取@Inject的id和clazz值,通過反射實例化clazz的對象,再反射賦值給field。這就是Spring那些框架的依賴注入的實現原理,有興趣的可以自己再優化一下。
讀取類的注解信息還有其它的幾個方法,在此不再一一說明,可以自行研究java.lang.reflect包。經過上面的說明,由此我們也可以知道注解僅僅是一種元數據,增強類、屬性、參數的描述,使用注解的關鍵在于獲取注解的信息,再通過反射的手段來實現注解想達成的功能。

總結

以上是生活随笔為你收集整理的java基础-注解Annotation原理和用法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。