一,概念
- Annotation(注解):一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
- Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的 Annotion对象,然后通过 Annotion对象 来获取注解里面的元数据。
- Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。从某些方面看,annotation 就像修饰符一样被使用,并应用于包、类 型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在 Annotation 的 “name=value” 结构对中。
什么是metadata元数据
元数据从 metadata 一词译来,就是“关于数据的数据”的意思。
元数据的功能作用有很多,比如:你可能用过 Javadoc 的注释自动生成文档。这就是元数据功能的一种。总的来说,元数据可以用来创建文档,跟踪代码的依赖性,执行编译时格式检查,代替已有的配置文件。如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:
编写文档:通过代码里标识的元数据生成文档
代码分析:通过代码里标识的元数据对代码进行分析
编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查
二,注解使用
package com.baidu.test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
/*
* 注解的使用
*
* 需求: 1.有一张用户表,字段包括姓名,年龄,id,邮箱
* 2.方便对每个字段或者字段的组合进行检索,并打印出Sql语句
* 3.使用方式要足够简单
*
* select * from info where name = "张三" and age = 11;
*
* 分析:1.首先应该考虑代码如何同数据库进行映射
* 2.查看Filter类,因为结构和数据库表最相似
* */
public static void main(String[] args) {
Filter filter1 = new Filter();
filter1.setAge(11);
filter1.setName("张三");
Filter filter2 = new Filter();
filter1.setName("李四");
String sql = query(filter1);
String sql2 = query(filter2);
System.out.println(sql);
System.out.println(sql2);
}
/**
*
* @param filter1
* @return 根据条件生成sql语句
*/
private static String query(Filter filter1) {
StringBuilder sb = new StringBuilder();
//1.获取到class
Class clazz = filter1.getClass();
//2.获取table的名字
boolean isExist = clazz.isAnnotationPresent(Table.class);
if (!isExist) {
return null;
}
Table table = (Table) clazz.getAnnotation(Table.class);
String tableName = table.value();
sb.append("select * from ").append(tableName).append(" where 1 = 1"); //where 1 = 1 测试,为了防止报错
//3.遍历所有的字段
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
//4.处理每个字段对应的sql
//4.1拿到字段的名字
boolean fExist = field.isAnnotationPresent(Column.class); //判断字段是否包含这个注解
if (!fExist) {
continue;
}
Column column = field.getAnnotation(Column.class);
String columName = column.value();
//4.2拿到字段的值 例如:字段age 拿到字段的值 getAge
//通过反射获取getAge方法 通过字段 拼接出来getAge
String fieldName = field.getName();
String methodName = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
Object fileValue = null;
try {
//通过反射得到方法
Method method = clazz.getMethod(methodName);
fileValue = method.invoke(filter1);
} catch (Exception e) {
e.printStackTrace();
}
if (fileValue == null || (fileValue instanceof Integer && (Integer)fileValue == 0)) {
continue;
}
sb.append(" and ").append(fieldName).append("=").append(fileValue+" ");
}
return sb.toString();
}
}
package com.baidu.test;
@Table("user") //使用注解将表名和字段对应
public class Filter {
@Column("user_name")
private String name;
@Column("age")
private int age;
@Column("email")
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
package com.baidu.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE}) //表示Table这个注解的作用域是类或者接口
@Retention(RetentionPolicy.RUNTIME) //生命周期是在运行时
public @interface Table {
String value(); //当只有一个值的时候默认使用 value()
}
package com.baidu.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD}) //作用域是在成员变量
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
输出:
select * from user where 1 = 1 and name=李四 and age=11
select * from user where 1 = 1