一、概念
Java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法
学习注解的作用:
-
学习注解能读懂别人写的代码,特别是框架相关的代码。
-
注解能让编程更加简洁,代码更加清晰。
-
会使用自定义注解是重中之重。
二、java常见注解
- @Override :示必须是覆盖父类的方法
- @Deprecated :方法过时了该方法被调用时会出先warning
- @Suppvisewarnings:忽略警告
- Spring注解
三、注解分类
1、按照运行机制分类:
-
源码注解: 只在源码中存在,编译成.class文件就不存在了。
-
编译时注解: 源码和.class文件中都存在。
-
运行时注解: 在运行时还会起作用,甚至影响运行逻辑。
2、按照来源分类:
-
来自JDK的注解
-
来自第三方的注解
-
自定义的注解
除上述之外还有“元注解”:给注解进行注解。
四、自定义注解
1、语法要求
- 使用@interface 定义注解
- 成员变量无参数无异常
- 成员变量可以赋值默认值,成员类型受限
- 只有一个成员变量时,成员名为value,使用时可以忽悠成员名
2、元注解
-
@Target:作用域,作用域方法、类和接口、
-
@Retention:生命周期:源文件source、编译class、运行runtime(自定义最常使用)
-
@Inherited:允许继承,只有类的继承且继承的类上才能使用
-
@Documented:生成javadoc时会包含注解信息
3、使用方法
在作用域类使用@注解名(成员变量=值)
4、解析注解
通过反射方法得到注解名和相关的参数值。
- 使用类加载器加载类
- 找到类上面的注解
- 拿到类注解实例
五、自定义注解示例
需求:
- 有一张用户表,字段包括:用户ID、用户名、昵称、年龄、性别、所在城市、邮箱、手机号;
- 使用java注解来对用户表的每个字段或字段的组合条件进行动态生成SQL查询语句。
1、定义注解
package dao;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
package dao;
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();
}
2、定义映射到数据库的user
package dao;
@Table("user")
public class User {
@Column("id")
private int id;
@Column("user_name")
private String userName;
@Column("nick_name")
private String nickName;
@Column("age")
private int age;
@Column("city")
private String city;
@Column("email")
private String email;
@Column("mobile")
private String mobile;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
}
3、根据参数动态解析返回查询
package dao;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReturnQuery {
public static String query(Object u){
StringBuilder sqlStrBuilder = new StringBuilder();
//1.获取到Class
Class c = u.getClass();
//判断是否包含Table类型的注解
if(!c.isAnnotationPresent(Table.class)){
return null;
}
//2.获取到table的名字
Table t = (Table) c.getAnnotation(Table.class);
String tableName = t.value();
//加入 where 1=1 ,是为了防止未来如果没有条件的情况下也不会报错
sqlStrBuilder.append("select * from ").append(tableName).append(" where 1=1");
Field[] fArray = c.getDeclaredFields(); //获取类属性的所有字段,
//3.遍历所有的字段
for (Field field : fArray) {
//4.处理每个字段对应的sql
//判断是否包含Column类型的注解
if(!field.isAnnotationPresent(Column.class)){
continue;
}
//4.1.拿到字段上面注解的值,即Column注解的值
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
//4.2.拿到字段的名
String filedName = field.getName();
//获取相应字段的getXXX()方法
String getMethodName = "get" + filedName.substring(0, 1).toUpperCase()
+ filedName.substring(1);
//字段的值
Object fieldValue = null;//属性有int、String等,所以定义为Object类
try {
Method getMethod = c.getMethod(getMethodName);
fieldValue = getMethod.invoke(u);
} catch (Exception e) {
e.printStackTrace();
}
//4.3.拼接sql
if(fieldValue==null || (fieldValue instanceof Integer && (Integer)fieldValue==0)){
continue;
}
sqlStrBuilder.append(" and ").append(filedName);
if(fieldValue instanceof String){
if(((String)fieldValue).contains(",")){
String[] values = ((String)fieldValue).split(",");
sqlStrBuilder.append(" in(");
for (String v : values) {
sqlStrBuilder.append("'").append(v).append("'").append(",");
}
sqlStrBuilder.deleteCharAt(sqlStrBuilder.length()-1);
sqlStrBuilder.append(")");
}
else{
sqlStrBuilder.append("=").append("'").append(fieldValue).append("'");
}
}
else if(fieldValue instanceof Integer){
sqlStrBuilder.append("=").append(fieldValue);
}
}
return sqlStrBuilder.toString();
}
}
4、测试
package dao;
public class Test {
public static void main(String[] args) {
User u1 = new User();
u1.setId(9); //查询id为9的用户
User u2 = new User();
u2.setUserName("JTZeng"); //模糊查询用户名为JTZeng的用户
u2.setAge(21);
User u3 = new User();
u3.setEmail("123@163.com,123@qq.com"); //查询邮箱有任意一个的用户
String sql1 = ReturnQuery.query(u1); //查询id为9的用户
String sql2 = ReturnQuery.query(u2); //查询用户名为JTZeng和年龄为21的用户
String sql3 = ReturnQuery.query(u3); //查询邮箱中有任意一个的用户
System.out.println(sql1);
System.out.println(sql2);
System.out.println(sql3);
}
}
结果: