注解分類
- 源碼注解:只在源碼中存在,編譯成.class文件就不存在了
- 編譯時注解:在源碼和.class文件中都存在
- 運行時注解:在運行階段起作用,甚至會影響運行邏輯
元注解
@Target 作用域
成員ElementType的取值
/** 類、接口、注解、枚舉 */
TYPE,
/** 字段 */
FIELD,
/** 方法 */
METHOD,
/** 參數(shù)聲明 */
PARAMETER,
/** 構(gòu)造方法聲明 */
CONSTRUCTOR,
/** 局部變量聲明 */
LOCAL_VARIABLE,
/** 注解聲明 */
ANNOTATION_TYPE,
/** 包聲明 */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
@Retention 聲明周期
成員RetentionPolicy的取值
/**
* 只在源碼中顯示,不參與編譯
*/
SOURCE,
/**
* 參與編譯,不參與運行(默認)
*/
CLASS,
/**
* 參與運行,可以通過反射讀取
*/
RUNTIME
@Inherited
允許子類繼承
@Documented
生成javadoc時包含注解信息
自定義注解
語法要求
- 使用@interface關(guān)鍵字定義注解
- 成員以無參無異常方式聲明
- 可以用default為成員指定一個默認值
- 成員的合法類型包括原始類型、String、Class、Annotation、Enumeration
- 若注解只有一個成員,則成員名必須為value(),在使用時有忽略成員名和賦值符號
- 注解類可以沒有成員(標識注解)
解析注解
通過反射獲取類、方法或成員上的運行時注解的信息,從而實現(xiàn)動態(tài)地控制程序運行的邏輯。
定義注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {
/**
* the description of the annotated element
*
* @return String
*/
String desc() default "";
/**
* the info of author
* @return
*/
String author();
}
解析
public class AnalysisAnnotation {
@Description(desc = "do1 method", author = "wch")
public void do1() {
System.out.println("do something...");
}
public static void main(String[] args) {
try {
Class c = Class.forName("com.wch.test.annotation.AnalysisAnnotation");
Method method = c.getMethod("do1");
boolean isExistAnnotation = method.isAnnotationPresent(Description.class);
if (isExistAnnotation) {
Description description = method.getAnnotation(Description.class);
System.out.println(description.desc());
}
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
仿JPA注解實例
定義Table注解
/**
* 標識表
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
/**
* 表名
* @return String
*/
String value();
}
定義Column注解
/**
* 表字段
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
/**
* 字段名
* @return String
*/
String value();
}
定義User實體類
與數(shù)據(jù)庫中的user表相映射
@Table("user")
public class User {
@Column("id")
private Integer id;
@Column("name")
private String name;
@Column("age")
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
注解結(jié)合反射動態(tài)生成sql
/**
* 通過獲取注解信息,以反射的形式生成sql語句
*/
public class Query {
private static final Logger log = LoggerFactory.getLogger(Query.class);
private static String query(User user) {
StringBuffer sb = new StringBuffer();
// 加載類對象
Class c = user.getClass();
// 獲取表名
boolean isExistTableName = c.isAnnotationPresent(Table.class);
if (!isExistTableName) {
return null;
}
Table table = (Table) c.getAnnotation(Table.class);
String tableName = table.value();
sb.append("SELECT * FROM ").append(tableName).append(" WHERE 1 = 1");
// 遍歷所有字段
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
// 獲取字段名
boolean isExistColumnName = field.isAnnotationPresent(Column.class);
if (!isExistColumnName) {
continue;
}
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
// 獲取字段名
String fieldName = field.getName();
// 獲取get方法名
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
// 獲取字段值
Object fieldValue;
try {
Method method = c.getMethod(getMethodName);
fieldValue = method.invoke(user);
} catch (Exception e) {
log.info(e.getMessage());
return null;
}
if (null != fieldValue) {
sb.append(" AND ").append(columnName).append(" = ");
if (fieldValue instanceof String) {
sb.append("'").append(fieldValue).append("'");
} else {
sb.append(fieldValue);
}
}
}
return sb.toString();
}
public static void main(String[] args) {
User user1 = new User();
user1.setId(1);
String query1 = Query.query(user1);
User user2 = new User();
user2.setName("wch");
String query2 = Query.query(user2);
User user3 = new User();
user3.setAge(21);
String query3 = Query.query(user3);
User user4 = new User();
user4.setId(1);
user4.setName("wch");
user4.setAge(21);
String query4 = Query.query(user4);
log.info("Query 1: {}", query1);
log.info("Query 2: {}", query2);
log.info("Query 3: {}", query3);
log.info("Query 4: {}", query4);
}
}