在現實生活中,貼標籤這種現象比比皆是。去超市,去商場,每一個或者每類物品都會有它的標籤,甚至在咱們本身身上也會有標籤,好比,程序猿、逗逼、單身狗、80/90後、屌絲……呵呵,太多了。有時候,咱們也會戲謔朋友同事,給他們貼個標籤逗逗樂。可是這篇的正題是註解,下面我會說說爲何我理解的註解就是貼標籤,雖然有時候也會稱它爲「扣帽子」。java
在java提供了四個元註解,元註解就是註解的註解。它們是:spring
1.@Target, 2.@Retention, 3.@Documented, 4.@Inherited
在咱們剛出生的時候,就已經被貼上標籤了,咱們的戶籍按照地域劃分,會被貼上河南河北、山東山西、湖南湖北等等23個省和四個直轄市中的其中一個。另外在咱們的生命過程當中也會經歷標籤的變換,小孩、未成年人、成年人、丈夫、妻子、父親、母親、爺爺奶奶等等。國家還會給咱們貼上一個最普通的標籤「公民」以及咱們的繼承的身份,農民或者城裏人。爲何要說這些呢,由於JAVA中提供的四個元註解要表達的東西和提到的有共通之處。sql
@Target說明了註解修飾的範圍,就好像咱們有地域劃分,而Java中也會有包、接口、類、枚舉、屬性、方法、構造函數等。那麼爲了表示不一樣的區別,註解是這麼寫的:app
一、包 @Target(ElementType.PACKAGE)
二、接口、類、枚舉、註解 @Target(ElementType.TYPE)
三、註解 @Target(ElementType.ANNOTATION_TYPE)
四、構造函數 @Target(ElementType.CONSTRUCTOR)
五、局部變量 @Target(ElementType.LOCAL_VARIABLE)
六、方法 @Target(ElementType.METHOD)
七、方法的參數 @Target(ElementType.PARAMETER)
@Retention表示了註解的生命週期。咱們在生命過程當中會隨着時間的變化而引發標籤的變化,那麼咱們的標籤自己也就說明了它有必定的生命週期,當咱們未滿18週歲的時候叫未成年人,在咱們滿18週歲的時候叫作成年人,等頭髮白了,走不動就被叫作老年人,而有的標籤會伴隨一輩子,例如男人或者女人。在JAVA中,註解也有它的生命週期,從源代碼到編譯後的Class文件,再到被JDK加載後的運行時就是整個週期。@Retention指定了它所要註解的註解的生命週期是什麼,它會存在多長時間。JAVA中咱們最多見的兩個註解@SuppressWarnings和@Override,他們就只會存在於源代碼中。下面是@Retention的取值:ide
一、在源代碼中保留 @Retention( RetentionPolicy.SOURCE)
二、在Class文件中保留 @Retention( RetentionPolicy.CLASS)
三、在運行時保留 @Retention( RetentionPolicy.RUNTIME)
@SuppressWarnings註解的源代碼以下:函數
package java.lang; import java.lang.annotation.*; import java.lang.annotation.ElementType; import static java.lang.annotation.ElementType.*; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { String[] value(); }
默認狀況下javadoc是不包括註解信息的,可是當某一個註解被貼上@Documented標籤的時候,那麼當某個類或者方法的使用了被貼上@Documented這個標籤的註解的時候,javadoc就會把註解信息也包含在生成的文檔中。這個註解就不過分解讀了,若是有興趣的能夠從網上自行查找相關資料。ui
@Inherited註解主要說明了一種繼承性,意思是子類能夠繼承父類中的該註解(注意:只有當被貼上@Inherited標籤的註解被用在類上的時候子類才能得到這個註解)。就像以前提到的,若是父母是農村戶口,那麼他們的孩子也默認就是農村戶口了。Spring中的@Qualifier註解,代碼以下:this
package org.springframework.beans.factory.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Qualifier { String value() default ""; }
@Qualifier註解能夠被用在字段、方法、方法參數、類、接口、註解、枚舉上,可是隻有@Qualifier被用在類上的時候才能被它的子類繼承,子類才能夠獲取到這個註解。spa
除了一些咱們生來就被貼上的標籤意外,咱們在平常生活中不論是主動的仍是被動都會去主動的給別人貼一些標籤以及被別人貼一些標籤。當咱們在公司,按照職能劃分,會被貼上不一樣的崗位標籤,便於安排工做;遲到,早退,全勤這些標籤用於考勤;優秀員工,技術達人,管理精英等標籤用來樹立標杆,有助於提升積極性和向心力。那麼這些標籤被創造出來有沒有用處呢,對於公司來講天然是有用處的。可是呢,逗逼這個標籤對公司來講有沒有用處呢,我想,除非公司願意由於員工逗逼頒發逗逼獎這纔有點用處,不然的話誰關心呢!貼個標籤大多數時候並不會影響正常的生活,除了我的或者組織關注了你身上的標籤的時候纔會有影響,就像如今不少人一看到河南人三個字就開罵了同樣……。其實這也是爲了說明,註解並不會影響程序的正常運行,有或者沒有並不影響什麼,只有關注了這些註解的程序得到而且解析了註解進行處理之後纔會更改程序自己的行爲。code
咱們知道JAVA的JDK中不少地方都用了註解,到咱們使用Spring的時候,註解就被使用的更普遍了,Spring用註解來對bean進行分類,註冊,注入以及管理,這些事情是Spring在掃描Bean的時候經過反射來獲取Bean的註解信息,配合完成Bean的自動裝配,進而進行管理,給咱們提供了豐富多彩的功能。下面寫一個利用反射來處理自定義註解的例子,這個例子就是簡單生成一個建表語句,代碼以下:
一、建立@Table註解
package person.lb.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 表名 * @author nobounds * */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Table { String value() default ""; }
二、建立@Column註解:
package person.lb.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 字段 * @author nobounds * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String name() default ""; String dataType() default "varchar(20)"; String comment() default ""; }
三、建立實體類Users:
package person.lb.annotation; @Table("users") public class Users { @Column(name="ID", dataType="int") private int id; @Column(comment="用戶名") private String userName; @Column(name="pwd", comment="密碼") private String password; @Column(dataType="varchar(25)", comment="郵箱") private String email; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
四、建立註解處理器AnnotationHandler:
package person.lb.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Field; public class AnnotationHandler { public static void main(String[] args) { StringBuilder sql = new StringBuilder("CREATE TABLE "); try { Class clazz = Class.forName("person.lb.annotation.Users"); //獲取Users類上的Table註解 Table tableAnnotation = (Table) clazz.getAnnotation(Table.class); //獲取表名 String tableName = tableAnnotation.value().toUpperCase(); if("".equals(tableName)) { tableName = clazz.getName().toUpperCase(); } sql.append(tableName); sql.append(" ( \n"); //獲取類中的全部字段 Field[] fields = clazz.getDeclaredFields(); for(Field field : fields) { //獲取字段上的全部註解 Annotation[] fieldAnnotations = field.getAnnotations(); if(fieldAnnotations.length > 0) { //遍歷註解 for(Annotation fieldAnnotation : fieldAnnotations) { //若是是@Field註解,那麼進行處理 if(fieldAnnotation instanceof Column) { //獲取字段名 String columnName = ((Column) fieldAnnotation).name().toUpperCase(); if("".equals(columnName)) { columnName = field.getName().toUpperCase(); } //獲取數據類型 String dataType = ((Column) fieldAnnotation).dataType().toUpperCase(); //獲取註釋 String comment = ((Column) fieldAnnotation).comment(); if("".equals(comment)) { sql.append(columnName + "\t" + dataType + ",\n"); } else { sql.append(columnName + "\t" + dataType + " COMMENT '" + comment + "',\n"); } } } } } sql.append(" ) "); System.out.println("生成的sql語句爲:\n" + sql.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
執行結果以下:
生成的sql語句爲: CREATE TABLE USERS ( ID INT, USERNAME VARCHAR(20) COMMENT '用戶名', PWD VARCHAR(20) COMMENT '密碼', EMAIL VARCHAR(25) COMMENT '郵箱', )
上面是一個簡單的生成sql的例子,例子中忽略了某些非空判斷,邏輯並不嚴謹,僅做爲參考使用。若是你們以爲有問題請留言!