自定義註解需配合元註解說明其生命週期與作用目標:
@Retention:SOURCE(源碼期)、CLASS(編譯期,默認)、RUNTIME(運行期,反射可見)。@Target:TYPE(類/介面)、FIELD(字段)、METHOD、PARAMETER、CONSTRUCTOR、LOCAL_VARIABLE 等。@Documented:包含在 Javadoc 中。@Inherited:允許子類繼承父類的該註解(僅針對 TYPE)。// 類級註解:映射表名、版本
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableMeta {
String name() default "";
int version() default 1;
}
// 字段級註解:映射列名、類型
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ColumnMeta {
String name() default "";
String jdbcType() default "VARCHAR";
boolean primaryKey() default false;
}
@TableMeta(name = "t_user", version = 2)
public class User {
@ColumnMeta(name = "id", jdbcType = "BIGINT", primaryKey = true)
private Long id;
@ColumnMeta(name = "user_name", jdbcType = "VARCHAR")
private String username;
@ColumnMeta(name = "email", jdbcType = "VARCHAR")
private String email;
// getter/setter 省略
}
public class AnnotationParser {
public static void parseEntity(Class<?> clazz) {
// 1. 解析類註解
TableMeta table = clazz.getAnnotation(TableMeta.class);
if (table == null) throw new IllegalArgumentException("缺少 @TableMeta");
System.out.println("表名: " + table.name() + ", 版本: " + table.version());
// 2. 解析字段註解
for (Field field : clazz.getDeclaredFields()) {
ColumnMeta col = field.getAnnotation(ColumnMeta.class);
if (col != null) {
System.out.printf("字段: %-15s 列名: %-15s 類型: %-10s PK: %b%n",
field.getName(), col.name(), col.jdbcType(), col.primaryKey());
}
}
}
public static void main(String[] args) {
parseEntity(User.class);
}
}
表名: t_user, 版本: 2 字段: id 列名: id 類型: BIGINT PK: true 字段: username 列名: user_name 類型: VARCHAR PK: false 字段: email 列名: email 類型: VARCHAR PK: false
@NotNull、@Size 結合攔截器/切面。value 且為唯一屬性時,使用時可省略 value =。null,需用空字符串或特定標記代替。RUNTIME,否則反射獲取不到。