一、原理

1. 注解的定义与约束

import java.lang.annotation.*;

/* 作用域: CONSTRUCTOR构造方法, FIELD字段, LOCAL_VARIABLE局部变量, 
 * METHOD方法, PACKAGE包, PARAMETER参数, TYPE接口类型
 */
@Target({ElementType.METHOD, ElementType.TYPE})
/* 生命周期: SOURCE源代码级不保留到class文件, CLASS级保留到class运行时丢弃, 
 * RUNTIME运行时存在可反射获取
*/
@Retention(RetentionPolicy.RUNTIME)
//允许子类继承注解(可选), 只支持继承class的注解不能继承interface的注解
@Inherited
//生成javadoc时会包含注解(可选)
@Deprecated
public @interface DemoAnn {
    /* 注解成员参数必须以类型名加无参无异常方法名指定
     * 如果只有一个成员参数必须名为value(), 没有成员参数的注解为标识注解
     * 成员参数类型只能是基础类型或String或class或注解
     */
    String desc();
    String author();
    int age() default 29;
}

 

2. 利用反射获取注解信息实例

import java.lang.annotation.Annotation;
import java.lang.reflect.*;

interface Action {
    @SuppressWarnings("deprecation")
    @DemoAnn(desc = "Method_Name Ann", author = "Athrun")
    String name();
    @Deprecated
    String action();
}

class Base {
    @SuppressWarnings("deprecation")
    @DemoAnn(desc = "BaseMethod1 Ann", author = "Athrun")
    public String fun1() {
        return "Base's fun1";
    }
    @SuppressWarnings("deprecation")
    @DemoAnn(desc = "BaseMethod2 Ann", author = "Athrun")
    public String fun2() {
        return "Base's fun2";
    }
    
    public String name() {
        return null;
    }
}

@DemoAnn(desc = "Class's Ann", author = "Athrun")
class Person extends Base implements Action {

    @Override
    public String name() {
        // TODO Auto-generated method stub
        return "Ghost";
    }

    
    @Override
    @SuppressWarnings("deprecation")
    @DemoAnn(desc = "Method_Action Ann", author = "Athrun")
    public String action() {
        // TODO Auto-generated method stub
        return null;
    }    
    
    //重写Base的fun2去掉了注解,输出中就不会出现父类fun2()注释内容
    @Override
    public String fun2() {
        return "Person's fun2";
    }
}

public class AnnTest {

    @SuppressWarnings("rawtypes")
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //解析注解
        try {
            //1. 使用类加载器加载类
            Class cl = Class.forName("org.znufe.anns.Person");
            //2. 寻找注解
            boolean isExist = cl.isAnnotationPresent(DemoAnn.class);
            if(isExist) {
                //3. 获取类上的注解
                DemoAnn demoAnn = (DemoAnn) cl.getAnnotation(DemoAnn.class);
                System.out.println("Ann's desc: " + demoAnn.desc() + ", author: " 
                        + demoAnn.author() + ", age: " + demoAnn.age());
            }
            //4. 获取方法上的注解
            //4.1 逐个方法查找
            Method[] methods = cl.getMethods();
            for(Method m : methods) {
                isExist = m.isAnnotationPresent(DemoAnn.class);
                if(isExist) {
                    DemoAnn demoAnn = (DemoAnn) m.getAnnotation(DemoAnn.class);
                    System.out.println("Ann's desc: " + demoAnn.desc() + ", author: " 
                            + demoAnn.author() + ", age: " + demoAnn.age());
                }
            }
            //4.2 直接获取方法上的所有注解, 然后筛选出DemoAnn类型注解
            for(Method m : methods) {
                Annotation[] annotations = m.getAnnotations();
                for(Annotation a : annotations) {
                    if(a instanceof DemoAnn) {
                        DemoAnn demoAnn = (DemoAnn) a;
                        System.out.println("Ann's desc: " + demoAnn.desc() + ", author: " 
                                + demoAnn.author() + ", age: " + demoAnn.age());
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
/* 输出如下:
 * Ann's desc: Class's Ann, author: Athrun, age: 29
 * Ann's desc: Method_Action Ann, author: Athrun, age: 29
 * Ann's desc: BaseMethod1 Ann, author: Athrun, age: 29
 * Ann's desc: Method_Action Ann, author: Athrun, age: 29
 * Ann's desc: BaseMethod1 Ann, author: Athrun, age: 29
 * */

 

二、模拟数据表关系对象映射的查询(只获取sql语句,省略实际查询过程)

1. Entity

/**
 * @category Entity
 * @author Athrun
 * User实体类
 */
@Table("user")
public class User {
    @Column("user_name")
    private String userName;
    @Column("pass_word")
    private String passWord;
    @Column("age")
    private int age;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

 

/**
 * @category Entity
 * @author Null's
 * Depart实体类
 */
@Table("depart")
public class Depart {
    @Column("leader")
    private String leader;
    @Column("depart_name")
    private String departName;
    @Column("num")
    private int num;
    public String getLeader() {
        return leader;
    }
    public void setLeader(String leader) {
        this.leader = leader;
    }
    public String getDepartName() {
        return departName;
    }
    public void setDepartName(String departName) {
        this.departName = departName;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
}

 

2. Annotation

/**
 * @author Athrun
 * Table注解用于保存对象对应表名
 */
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();
}

 

/**
 * @author Athrun
 * Column注解用于标识对象属性在数据表中对应的字段
 */
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();
}

 

3. Impl

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @category Impl
 * @author Athrun
 * 用于创建初始数据并生成查询语句
 */
public class AnnImpl {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        User u1 = new User();
        u1.setUserName("aaa");
        User u2 = new User();
        u2.setPassWord("123456,654321");
        User u3 = new User();
        u3.setAge(29);
        User u4 = new User();
        u4.setAge(25);
        u4.setPassWord("123456");
        String sql1 = query(u1);
        String sql2 = query(u2);
        String sql3 = query(u3);
        String sql4 = query(u4);
        System.out.println(sql1);
        System.out.println(sql2);
        System.out.println(sql3);
        System.out.println(sql4);
        
        Depart depart = new Depart();
        depart.setDepartName("Develop");
        depart.setLeader("Athrun");
        depart.setNum(10);
        String sql = query(depart);
        System.out.println(sql);
    }
    
    private static<T> String query(T t) {
        StringBuilder sb = new StringBuilder();
        //1. 获取class
        Class cl = t.getClass();
        //2. 获取table的名字
        boolean exists = cl.isAnnotationPresent(Table.class);
        if(!exists) {
            return null;
        }
        Table table = (Table) cl.getAnnotation(Table.class);
        String tableName = table.value();
        sb.append("select * from ").append(tableName).append(" where 1=1");
        //3. 遍历所有字段
        Field[] fields = cl.getDeclaredFields();
        //4. 处理每个字段对应sql
        //只关心被注解的属性
        for(Field f : fields) {
            //4.1 寻找注解
            boolean fieldExists = f.isAnnotationPresent(Column.class);
            if(!fieldExists) {
                continue;
            }
            //4.2 获取字段名
            Column column = f.getAnnotation(Column.class);  //获取注解
            String columnName = column.value();  //获取注解里保存的字段值
            //4.3 获取字段值
            String fieldName = f.getName();
            String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase()
                    + fieldName.substring(1);
            Object fieldValue = null;   //因为变量有各种类型, 用Object最为保险
            try {
                Method getMethod = cl.getMethod(getMethodName);
                fieldValue = getMethod.invoke(t);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //4.4 拼装sql
            //只关心有实际值的属性
            if(fieldValue == null || (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {
                continue;
            }
            sb.append(" and ").append(columnName);
            if(fieldValue instanceof String) {
                if(((String) fieldValue).contains(",")) {
                    String[] values = ((String) fieldValue).split(",");
                    sb.append(" in(");
                    for(String v : values) {
                        sb.append("'").append(v).append("'").append(", ");
                    }
                    sb.deleteCharAt(sb.length() - 1);
                    sb.deleteCharAt(sb.length() - 1);
                    sb.append(")");
                }else {
                    sb.append(" = ").append("'").append(fieldValue).append("'");
                }
            }else if(fieldValue instanceof Integer){
                sb.append(" = ").append(fieldValue);
            }
        }
        return sb.toString();
    }
}
/*
 * 输出如下:
 * select * from user where 1=1 and user_name = 'aaa'
 * select * from user where 1=1 and pass_word in('123456', '654321')
 * select * from user where 1=1 and age = 29
 * select * from user where 1=1 and pass_word = '123456' and age = 25
 * select * from depart where 1=1 and leader = 'Athrun' and depart_name = 'Develop' and num = 10
 */