java注解前世今生

<h4>前序:</h4>
很開心下了班以后坐在電腦前面寫這篇文章。注解Annotation我們常常見到jdk中的@override、@Deprecated、@SuppressWarnings 還有我本人認為非常優秀的開源項目spring中的IOC的@controller、@autowired和AOP的@Around @Before @After還有hibernate等我就不都枚舉了。既然用的地方這么多所以我們就還是有必要揭開它的面紗看看它到底是怎么玩的。
<h4>1、屬性全解</h4>
Java中提供了四種元注解,專門負責注解其他的注解,分別如下:
<pre>@Retention @Target @Documented @Inheried </pre>
先拿@override 的源碼來作為一個切入點:
<pre>
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
</pre>
@Target:說明了Annotation所修飾的對象范圍,取值在一個枚舉ElementType中,查看源碼(局限于1.7。since1.8以后又新增了2個)
<pre>
public enum ElementType {
TYPE, 用于描述類、接口(包括注解類型) 或enum聲明
FIELD, 成員變量、對象、屬性(包括enum實例)
METHOD, 方法聲明
PARAMETER, 參數聲明
CONSTRUCTOR, 構造器聲明
LOCAL_VARIABLE, 局部變量聲明
ANNOTATION_TYPE, 元注解,有興趣的可以看看@Retention、@Target、@Documented、@Inheried的@Target(ElementType.ANNOTATION_TYPE)都是如此
PACKAGE 包聲明
}
</pre>
@Retention:表示需要在什么級別保存該注釋信息(生命周期)。可選的RetentionPoicy參數包括:
<pre>
public enum RetentionPolicy {
SOURCE, 停留在java源文件,編譯器被丟掉
CLASS, 停留在class文件中,但會被JVM丟棄(默認)
RUNTIME 內存中的字節碼,JVM將在運行時也保留注解,因此可以通過反射機制讀取注解的信息,所以我們自己開發注解的話一般都是RUNTIME,這樣的話就可以通過注解來搞搞
}
</pre>
@Documented:一個簡單的Annotations標記注解,表示是否將注解信息添加在java文檔中。這個我們實際使用的會相對很少,因為我們大多會用在功能實現上。

@Inherited:指定Annotation具有繼承性,上個例子:
<pre>
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedDemo {
}
//父類使用了Inherited注解
@InheritedDemo
public class Father {
}
//子類驗證對于InheritedDemo注解是否有傳遞性
public class Child extends Father {
public static void main(String[] args) {
//輸出為true
System.out.println(Child.class.isAnnotationPresent(InheritedDemo.class));
}
}
</pre>
<h4>2、編寫自己的注解</h4>
記得最早期的時候在一家金融公司有用到注解的一個場景是,定義類中的每個屬性的名稱、類型及描述,好吧我們就開始著手寫代碼吧:
<pre>
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldDesc {
//定義數據類型枚舉
enum DataType{String,Integer,Long,Boolean,Double};
//名稱
String name() ;
//數據類型
DataType dataType();
//中文描述
String desc() default "";
}
</pre>
<pre>
public class AnnationStudent {
@FieldDesc(name = "id", dataType = DataType.Integer, desc = "id")
private int id;
@FieldDesc(name = "name", dataType = DataType.String, desc = "名稱")
private String name;
@FieldDesc(name = "age", dataType = DataType.Integer, desc = "年齡")
private int age;
@FieldDesc(name = "telNo", dataType = DataType.String, desc = "手機號碼")
private String telNo;
public static void main(String[] args) {
Field[] fieldList = AnnationStudent.class.getDeclaredFields();
if (ArrayUtils.isNotEmpty(fieldList)) {
for (Field field : fieldList) {
Annotation[] annotationList = field.getAnnotations();
if (ArrayUtils.isNotEmpty(annotationList))
for (Annotation annotation : annotationList) {
if (annotation instanceof FieldDesc) {
FieldDesc desc = (FieldDesc) annotation;
System.out.println(desc.name() + " ### " + desc.dataType() + " ### " + desc.desc());
}
}
}
}
}
}


輸出結果為:
id ### Integer ### id
name ### String ### 名稱
age ### Integer ### 年齡
telNo ### String ### 手機號碼
</pre>
這應該是一個完整的注解過程了吧。還有一個小技巧就是當我們給注解的屬性賦值時,如果里面有個value屬性,我們使用注解時可以不指定名稱,自動會指定到value賦值:
<pre>
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String value() default "";
String name() default "";
}
@Test("dadawd")
public class TE { <b>編譯通過,如果Test 沒有叫value的屬性時編譯會報錯</b>
}
</pre>
這點在spring中的注解里面很常見。
<h4>3、談談注解在類似hibernate等框架中的應用</h4>
也許不一定是hibernate,但它們定義pojo實體的實現思想是一樣的:
<pre>
@Entity
@Database(name="TestDB")
@Table(name="test_table")
public class TestEntity {
@Id
@Column(name="ID")
@GeneratedValue(strategy = GenerationType.AUTO)
@Type(value=Types.BIGINT)
private Long iD;</br>
@Column(name="Name")
@Type(value=Types.String)
private Long name;</br>
@Column(name="SourceType")
@Type(value=Types.INTEGER)
private Integer sourceType;</br>
public Long getiD() {
return iD;
}
public void setiD(Long iD) {
this.iD = iD;
}
public Long getName() {
return name;
}
public void setName(Long name) {
this.name = name;
}
public Integer getSourceType() {
return sourceType;
}
public void setSourceType(Integer sourceType) {
this.sourceType = sourceType;
}
}
</pre>
如何使用定義的@Database、@Table呢?
<pre>
//<b>獲取數據庫名</b>
public String getDatabaseName() {
Database db = clazz.getAnnotation(Database.class);
if (db != null && db.name() != null)
return db.name();
throw new RuntimeException("The entity must configure Database annotation.");
}
//<b>獲取表名</b>
public String getTableName() {
Table table = clazz.getAnnotation(Table.class);
if (table != null && table.name() != null)
return table.name();
Entity entity = clazz.getAnnotation(Entity.class);
if ( entity != null && (!entity.name().isEmpty()) )
return entity.name();
return clazz.getSimpleName();
}
</pre>
這就是注解的使用所在。
<h4>4、結束語</h4>
我所理解的注解就是打標簽下定義,比如我們常說某人是屌絲、高富帥、白富美,當知道某人是高富帥你又能反向推斷出來是長的高、有錢、又帥這么一類人。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容

  • 本文章涉及代碼已放到github上annotation-study 1.Annotation為何而來 What:A...
    zlcook閱讀 29,230評論 15 116
  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一種元程序中的元素關聯任何信息和...
    九尾喵的薛定諤閱讀 3,206評論 0 2
  • 在我走過的二十多個春去秋來的日子里,我每天都在尋找一樣珍貴的東西。它并不是什么金銀珠寶,也并非山珍海味,它卻是一種...
    高樓休獨依閱讀 472評論 1 4
  • 怎么能夠忘懷 六十八年的風雨不改 歷經磨難征程不退 先輩相攜背靠背 脊梁撐住天地 不愿天黑 刻不容緩不能再等待 舉...
    緣起緣落是哀愁閱讀 119評論 0 0
  • 古文今讀: 【原文】 怨在不舍小過.患在不預定謀 【譯文】 怨恨產生在對小的過失耿耿于懷,抓住不放。也是格局問題,...
    清靜道人閱讀 310評論 0 0