5.6其他WEB技术——利用反射注解写通用DAO层

JAVAWEB文章索引点这里
1,注解简单介绍:
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
常见注解:

注解形式 注解作用
@Override 告诉编译器强制对方法进行覆盖
@SuppressWarnings 告诉编译器压制代码中出现的警告
@Deprecated 在运行时让方法提示过期

注解的定义
以下定义的一个注解可以用于类和方法上,在运行时依旧有效。name属性默认为”注解测试”,有一个String类型数组属性value(使用该属性时不可省略等号)。
当注解有其只有一个属性名为value时,使用注解时候可以不加等号。
元注解:
@Target
TYPE: 注解可以用在类上
FIELD:注解可以用在属性上
METHOD:用在方法上
PARAMETER:用在参数声明上面
CONSTRUCTOR:用在构造方法上面
LOCAL_VARIABLE:用在本地变量上面
@Retention
SOURCE: 该注解只在源码中有效!
CLASS: 该注解在源码中,和字节码中有效(默认)
RUNTIME: 该注解在源码中,和字节码中,运行字节码中有效

package com.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoTest {
    String name() default "注解测试";
    String[] value();
}

案例:
1,建立一张表person2(id,name)
2,BaseDao等类中使用的反射+泛型技术可到文章第一行“文章索引”连接中找

表注解:

package com.anno;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String tableName();
}

表属性注解:

package com.anno;

import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table_para {
    String parameter();
}

Person类:

package com.bean;
import com.anno.*;
interface Eatable{}
@Table(tableName = "person2")
public class Person implements Eatable{
    @Table_para(parameter="pid")
    private int id;
    @Table_para(parameter="pname")
    String name;
    public Person() {
        super();
    }
    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public boolean equals(Object obj) {
        Person person = (Person)obj;
        return this.id == person.id && this.name == person.name;
    }
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + "]";
    }
}

MyBeanListHandler类是自己封装的工具类,实现了apache的dbutils中的ResultSetHandler类

package com.dbutils;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.dbutils.ResultSetHandler;
import com.anno.Table_para;
import java.util.*;

public class MyBeanListHandler<T> implements ResultSetHandler {
    private Class t_class;

    public MyBeanListHandler(Class t_class) {
        this.t_class = t_class;
    }

    @Override
    public Object handle(ResultSet rs) throws SQLException {
        //获取到属性数量
        int count = rs.getMetaData().getColumnCount();
        List<T> list = new ArrayList<>();
        while(rs.next()) {
            try {
            //创建一个bean对象
             T obj = (T) t_class.newInstance();
             for(int i = 1; i <= count; i++) {
                //获取第i列的属性值
                Object value = rs.getObject(i);
                //获取第i列的表中的属性名
                String colName = rs.getMetaData().getColumnName(i);
                //获取javabean中的属性对象
                Field[] fields = t_class.getDeclaredFields();//注意不要使用getFields(),这样获取不到私有化属性
                for (Field field : fields) {
                    //对于每个属性,获取出它们的注解上的属性名
                    Table_para para = field.getAnnotation(Table_para.class);
                    String paraName = para.parameter();
                    //当某个javabean的属性注解上的参数名和表中的属性名对上了,对当前这个javabean属性赋值
                    if(paraName.equals(colName)) {
                            field.setAccessible(true);
                            field.set(obj, value);
                            break;
                    }
                }
             }
                list.add(obj);
            } catch (Exception e) {
                e.printStackTrace();
              }
        }
        return list;
    }

}

BaseDao:

package com.dao;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.*;

import org.apache.commons.dbutils.QueryRunner;
import com.anno.Table;
import com.dbutils.DBUtils;
import com.dbutils.MyBeanListHandler;

public class BaseDao_Anno<T> {
    Class T_class;
    String tableName;
    public BaseDao_Anno() {
        //获取到泛型class
        Type type = this.getClass().getGenericSuperclass();
        ParameterizedType ptype= (ParameterizedType)type;
        Type[] actTypeArgs = ptype.getActualTypeArguments();
        T_class = (Class)actTypeArgs[0];
        //获取表名
        Table table = (Table)T_class.getAnnotation(Table.class);
        tableName = table.tableName();
    }
    public List<T> selectAll() {
        try {
            String sql = "select * from "+ tableName;
            QueryRunner qr = new QueryRunner(DBUtils.getDataSource());
            return (List<T>)qr.query(sql, new MyBeanListHandler<T>(T_class));
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

service:

package com.service;

import java.util.*;

import org.junit.jupiter.api.Test;

import com.bean.*;
import com.dao.PersonDao;
public class MyService {
    public List<Person> getPersonList(){
        return new PersonDao().selectAll();
    }
    @Test
    public void test() {
        for (Person person : getPersonList()) {
            System.out.println(person.toString());
        }
    }
}

运行结果:

Person [id=1, name=东方不败]
Person [id=2, name=岳不群]

猜你喜欢

转载自blog.csdn.net/smallhc/article/details/81100850