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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java 注解编程

發(fā)布時間:2024/9/30 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 注解编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、注解介紹

注解(Annotation) 是 jdk1.5 版本以后引入的一個新特性,注解可以說是類反射的延伸,在一些需要配置文件的應(yīng)用中,可以使用注解替代配置文件,從而提高應(yīng)用的靈活。比如 常見的 @Autowired,@Controller 等。

下面是 Java 底層內(nèi)置的幾個注解

@Override: 只適用于方法,表示重寫父類中的方法

@Deprecated: 表示某各類或方法已過時,比如 Date 類中的 toLocaleString() 方法

@SuppressWarnings: 抑制編譯器的警告

二、元注解

元注解用于修飾注解,用于約束注解的作用范圍,注解級別等,下面是 Java 提供的 4 種元注解

@Target:指定注解使用的位置,@Target 中有一個 ElementType 數(shù)組,因此被 @Target 注解修飾的注解可以在多個位置上使用。下面是 ElementType 枚舉中的一些屬性(只列舉一些常用的屬性)

  • TYPE:能在類、接口(包含注解類型)和枚舉類型上使用
  • FIELD:只能在屬性上使用
  • METHOD:只能在方法上使用
  • ……

@Retention:用于表示該注解可以保留的作用域,@Retention 注解包含一個 RetentionPolicy 屬性,通過這個屬性來設(shè)置注解的保留域。RetentionPolicy 是一個枚舉,其中有 3 個屬性,如下

  • SOURCE:只在源代碼中顯示,在編譯成 .class 文件的時候會被丟棄
  • CLASS:編譯器會把注解記錄在 .class 文件中,當(dāng)程序運(yùn)行時,虛擬機(jī)不會保留該注解
  • RUNTIME:當(dāng)程序運(yùn)行時,也會被保留,因此可以通過反射技術(shù)獲取該類型注解中的一些信息

@Documented:被該注解修飾的類可以使用 javadoc 工具生成文檔,這里就不演示了

Inherited:如果子類繼承了被 Inherited 修飾的注解,則子類也自動擁有父類中的注解

下面我們通過個例子來加深下理解,下面是 @Deprecated 注解的底層實現(xiàn)

/** * 表示可以被生成文檔 * 在程序運(yùn)行時也會被保留 * 可以使用在構(gòu)造器,屬性,方法,類或接口,包上等 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) public @interface Deprecated { }

三、反射注解

jdk1.5 在 java.lang.refelect 包下新增了 AnnotatedElement 接口,該接口中提供了一些用于反射注解的方法,如下

下面通過一個例子來解析注解

自定義 @MyAnno 注解

/*** @Target 約束該注解只能作用于類接口或枚舉上* @Retention 表示這是一個運(yùn)行時注解,可以通過反射技術(shù)獲取注解中的信息*/ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnno {String username();int age() default 18; }

Person 類,使用 @MyAnno 注解標(biāo)識

@MyAnno(username = "張三") public class Person { }

MainDriver 測試類

public class MainDriver {public static void main(String[] args) {// 通過反射獲得 Person 類的 class 對象Class<Person> clazz = Person.class;if (clazz.isAnnotationPresent(MyAnno.class)) {// 通過 class 對象獲取 MyAnno 注解對象MyAnno anno = clazz.getAnnotation(MyAnno.class);// 獲取注解中的屬性值String username = anno.username();int age = anno.age();System.out.println(username + " " + age);} else {System.out.println("該類上沒有注解");}} }

四、注解與反射的綜合應(yīng)用

這里我們模擬一下 Spring Data JPA 中有關(guān)注解的實現(xiàn),使用注解與反射技術(shù)拼接查詢的 SQL 語句

自定義 @Table 注解

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Table {String value(); }

自定義 @Column 注解

@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Column {String value(); }

與數(shù)據(jù)庫映射的實體 Student 類

/*** 當(dāng)注解中只有一個 value 屬性時,可以直接定義注解屬性值*/ @Table("student") public class Student {@Column("id")private int id;@Column("user_name")private String username;@Column("age")private int age;@Column("city")private String city;@Column("phone")private String phone;// 省略 get 與 set 方法 }

注解解析 MainDriver 類

public class MainDriver {public static void main(String[] args) throws Exception {Student student1 = new Student();student1.setUsername("張三");student1.setAge(18);student1.setCity("hangzhou");String s1 = query(student1);System.out.println(s1);Student student2 = new Student();student2.setUsername("李四");student2.setPhone("12345678977");String s2 = query(student2);System.out.println(s2);}public static String query(Student student) throws Exception {StringBuilder sb = new StringBuilder();Class<?> clazz = student.getClass();boolean tableAnnoExits = clazz.isAnnotationPresent(Table.class);// 判斷 class 對象上是否有 @Table 注解if (!tableAnnoExits) {return null;}// 獲取 @Table 注解中的表名,拼接 SQlTable table = clazz.getAnnotation(Table.class);String tableName = table.value();sb.append("SELECT * FROM " + tableName + " WHERE 1 = 1");// 獲取 class 對象中的所有字段并遍歷Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {boolean fieldAnnoExits = field.isAnnotationPresent(Column.class);// 判斷字段上是否含有 @Column 注解if (!fieldAnnoExits) {continue;}// 獲取注解中的字段名Column column = field.getAnnotation(Column.class);String columnName = column.value();// 通過 get() 方法獲取傳入的字段值String fieldName = field.getName();String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);Method method = clazz.getMethod(getMethodName);Object fieldValue = method.invoke(student);if (fieldValue == null || (fieldValue instanceof Integer && (Integer)fieldValue == 0)) {continue;}// 接著拼接 SQL 語句sb.append(" AND ").append(columnName).append(" = ");if (fieldValue instanceof String) {sb.append("'").append(fieldValue).append("'"); } else if (fieldValue instanceof Integer) {sb.append(fieldValue);}}return sb.toString();} }

執(zhí)行結(jié)果

GitHub 代碼地址,點我前往~

總結(jié)

以上是生活随笔為你收集整理的Java 注解编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。