註解含義
註解是JDK1.5以後纔有的新特性,它至關於一種標記,在程序中加入註解就等於爲程序打上某種標記,以後又經過類的反射機制
來解析註解。java
JDK1.5以後內部提供的三個註解mysql
@Deprecated #廢棄,過期。 @Override #重寫、覆蓋。 @SuppressWarnings #壓縮警告。
示例
sql
@SuppressWarnings("deprecation") public class AnnotationTest { //四、這裏稱爲壓縮警告註解,能夠在類上也能夠放在方法上,由於該方法用了個已通過期的方法.getYear(),因此會發出警告 //加上這個註解代表取消對deprecation的警告,那麼該方法裏有過期方法也不會發出預警。同時getYear()的那條橫線也消失了。 @SuppressWarnings("deprecation") public static void main(String[] args) { //一、這裏的.getYear()方法畫了一條橫線表示此方法已通過時了,裏面方法加上了@Deprecated註解 new Date().getYear(); } //二、這裏我經過@Deprecated註解自定義一個已通過時不建議使用的方法。 @Deprecated public String getName() { return "小小"; } //三、重寫(覆蓋)父類Object的toString()方法 @Override public String toString() { return "小小"; } }
註解示意圖
數據庫
示例
數組
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface AnCode {//使用@interface關鍵字定義註解 //若是隻有一個屬性 強烈建議取名爲value String value() default ""; }
在自定義註解上面有四個註解,咱們稱爲元註解
,下面一個一個解釋。app
取值(ElementType)有: 一、CONSTRUCTOR: 用於描述構造器 二、FIELD: 用於描述域(字段申明) 三、LOCAL_VARIABLE:用於描述局部變量 四、METHOD: 用於描述方法 五、PACKAGE: 用於描述包 六、PARAMETER: 用於描述參數 七、TYPE: 用於描述類、接口(包括註解類型) 或enum聲明 八、TYPE_PARAMETER:輸入參數申明(JDK1.8) 九、TYPE_USE: 使用類型(JDK1.8)
取值(RetentionPoicy)有: 一、SOURCE: 在源文件中有效(即源文件保留) 二、CLASS: 在class文件中有效(即class保留) 三、RUNTIME: 註解永久保留,能夠被VM加載時加載到內存中
通常框架註解和咱們自定義註解採用的幾乎都是RUNTIME
,由於只有這個才能運行時經過反射來獲取註解中的數據。框架
概念
: @Inherited闡述了某個被標註的類型是被繼承的。若是一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。ide
注意
:@Inherited annotation類型是被標註過的class的子類所繼承。類並不從它所實現的接口繼承annotation,方法並不從它所重載的方法繼承annotation
解釋
: 好比A繼承B,B類的上面有一個註解@A帶有元註解@Inherited 那麼A也能夠擁有B父類的這個註解@A,但接口實現是不能夠的。同時須要指出@A註解是須要元註解@Retention(RetentionPolicy.RUNTIME)。工具
參考文章:java @Inherited註解的做用測試
概念
:描述其它類型的annotation應該被做爲被標註的程序成員的公共API,所以能夠被例如javadoc此類的工具文檔化。
一、只能用public或默認(default)這兩個訪問權修飾.例如,String value();這裏把方法設爲defaul默認類型; 二、參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和 String,Enum,Class,annotations等數據類型,以及這一些類型的數組; 三、若是隻有一個參數成員,最好把參數名稱設爲"value",後加小括號(也能夠不加小括號)
目標
實現一個簡單的經過註解生成SQL查詢語句。
先建立兩個註解
@Table表名註解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Table { //數據庫表名屬性 String value() default ""; }
@Column字段名註解
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { //數據庫表字段名稱和實體屬性映射 String value() default ""; }
User實體
@Table("t_user") public class User { /** * 用戶Id */ @Column("user_id") private Integer userId; /** * 用戶年齡 */ @Column("age") private Integer age; public User(Integer userId, Integer age) { this.userId = userId; this.age = age; } //添加get和set方法 }
解析註解類
public class Query { public static String query(Object object) throws Exception{ StringBuilder sql = new StringBuilder(); //1.利用反射獲取Class Class c = object.getClass(); //2.獲取Table的名字 boolean isExist = c.isAnnotationPresent(Table.class); if (!isExist) { return null; } Table t = (Table) c.getAnnotation(Table.class); //三、獲取註解上的value值 String tableName = t.value(); sql.append("select * form ").append(tableName).append(" where 1 = 1 "); //4.遍歷全部的屬性字段 Field[] fArray = c.getDeclaredFields(); for (Field field : fArray) { //處理每一個字段對應的sql boolean fExist = field.isAnnotationPresent(Column.class); if (!fExist) { continue; } Column column = field.getAnnotation(Column.class); //數據庫字段名 String columnName = column.value(); //五、將user_id 變成 userId String[] columns = columnName.split("_"); StringBuilder columnBuilder = new StringBuilder(); for (int i = 0; i < columns.length; i++) { String s = columns[i]; columnBuilder.append(s.substring(0, 1).toUpperCase()).append(s.substring(1)); } //六、活動屬性值 String getMethodName = "get" + columnBuilder.toString(); //get方法名 Method getMethod = c.getMethod(getMethodName); Object fieldValue = getMethod.invoke(object);//類字段值 //七、拼裝sql sql.append(" and ").append(columnName).append(" = ").append(fieldValue); } return sql.toString(); } }
測試類
public static void main(String[] args) throws Exception { User user = new User(001, 4); String query = Query.query(user); System.out.println("query = " + query); }
運行結果
經過這個小案例實現了經過註解的方式,生成sql語句。
只要本身變優秀了,其餘的事情纔會跟着好起來(少將20)