注解分类
- 源码注解:只在源码中存在,编译成.class文件就不存在了
- 编译时注解:在源码和.class文件中都存在
- 运行时注解:在运行阶段起作用,甚至会影响运行逻辑
元注解
@Target 作用域
成员ElementType的取值
/** 类、接口、注解、枚举 */
TYPE,
/** 字段 */
FIELD,
/** 方法 */
METHOD,
/** 参数声明 */
PARAMETER,
/** 构造方法声明 */
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关键字定义注解
- 成员以无参无异常方式声明
- 可以用default为成员指定一个默认值
- 成员的合法类型包括原始类型、String、Class、Annotation、Enumeration
- 若注解只有一个成员,则成员名必须为value(),在使用时有忽略成员名和赋值符号
- 注解类可以没有成员(标识注解)
解析注解
通过反射获取类、方法或成员上的运行时注解的信息,从而实现动态地控制程序运行的逻辑。
定义注解
@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实体类
与数据库中的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 +
'}';
}
}
注解结合反射动态生成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);
}
}