java注解学习笔记
一、jdk中的注解
jdk中都属于编译时注解,在编译前就会提示错误,总共有两种注解:
- @Deprecated 注解
表示方法已过时 - @Suppress Warning注解:忽略由Deprecated注解造成的警告
二、java第三方注解
这里只列举了Spring和Mybatis中常见的几个
- Spring中的注解
- @Autowired注解
- @Service注解
- @Repository注解
- Mybatis中的注解
- @InsertProvider
- @UpdateProvider
- @Options
三、注解的分类
- 源码注解
- 编译时注解
- 运行时注解
- 元注解:给注解进行注解
- @Target(ElementType.XXXX)
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
1. CONSTRUCTOR:用于描述构造器
2. FIELD:用于描述域即类成员变量
3. LOCAL_VARIABLE:用于描述局部变量
4. METHOD:用于描述方法
5. PACKAGE:用于描述包
6. PARAMETER:用于描述参数
7. TYPE:用于描述类、接口(包括注解类型) 或enum声明
最常用的TYPE(描述类)、METHOD(描述方法)、FIELD(描述成员变量) - @Retention(RetentionPolicy.RUNTIME)
- Inherited :是一个标记注解。
@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。- Documented :是一个标记注解,表示可用于javadoc工具的文档化
- @Target(ElementType.XXXX)
四、自定义注解
成员类型是受限的,合法的类型包括原始类型及String, Class, Annotation, Enumeration
同一个类文件只能被同一个类加载器对象加载一次
最简化的注解定义:
@Target({ ElementType.TYPE}) //定义在类上的注解
@Retention(RetentionPolicy.RUNTIME) //运行时注解
@Inherited //可被继承
@Documented //可用于文档化
public @interface UdfAnnotation {
String value();
}
五、代码实操
通过反射机制获取由注解标记的信息并构建sql查询语句
/**
* Person实体类,通过Table和Column注解标记表名和列明
*/
@Table("person")
public class Person {
@Column("id")
private String id;
@Column("name")
private String name;
@Column("age")
private Integer age;
public String getId() {
return id;
}
public void setId(String 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 "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Column自定义注解
*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
public String value();
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Table自定义注解,用于标记表名
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
public String value();
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 测试类,用于从注解中获取信息并构建sql语句
*/
public class Test {
public static void main(String[] args){
Person p1 = new Person();
p1.setId("1");
Person p2 = new Person();
p2.setName("kevin,lily");
Person p3 = new Person();
p3.setAge(10);
String q1 = query(p1);
String q2 = query(p2);
String q3 = query(p3);
System.out.println(q1);
System.out.println(q2);
System.out.println(q3);
}
public static String query(Object obj){
StringBuilder sql = new StringBuilder();
try {
Class c = Class.forName("com.example.demo.bases.reflect.project.Person");
if (c.isAnnotationPresent(Table.class)){
Table table = (Table)c.getAnnotation(Table.class);
String tableName = table.value();
//System.out.println(tableName);
sql.append("select * from ").append(tableName).append(" where 1=1");
Field[] fields = c.getDeclaredFields();
for(Field field : fields){
String columnName = ((Column)field.getAnnotation(Column.class)).value();
//System.out.println("列名:"+columnName);
// 得到方法名,并利用invoke通过方法名获取到参数值
String methodName = "get"+columnName.substring(0,1).toUpperCase()+columnName.substring(1);
//System.out.println("方法名:"+methodName);
Method method = c.getDeclaredMethod(methodName);
Object mValue = method.invoke(obj);
//System.out.println("方法值:"+mValue);
if (mValue instanceof Integer){
sql.append(" and ").append(columnName).append("=").append(mValue);
}
if (mValue instanceof String){
if (((String) mValue).contains(",")){
String[] values = ((String)mValue).split(",");
for (String value : values){
sql.append(" and ").append(columnName).append("=").append("'").append(value).append("'");
}
}else{
sql.append(" and ").append(columnName).append("=").append("'").append(mValue).append("'");
}
}
}
}
}catch (Exception e){
e.printStackTrace();
}
return sql.toString();
}
}
运行结果: