内省(Introspector) 是Java 语言对 JavaBean 类属性、事件的一种缺省处理方法。
将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。
getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。
通过内省机制改进Orm类,代码如下:
package orm;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import util.JdbcUtils;
/**
*
* @author fengzb
*
* @param <T>
*/
public class Orm2<T> {
private static final int NOT_FOUND = -1;
/**
* 获得映射数据库后的一个装配好的实体对象bean
*
* @param sql
* @param clazz
* @return
* @throws Exception
*/
public T getBean(String sql, Class<T> clazz) throws Exception {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
T t = clazz.newInstance();
int[] pos = mapColumnsToProperties(rs, clazz);
if(rs.next()){
callSetter(t,pos,rs);
}
return t;
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
/**
* 获得映射数据库后的装配好的实体对象bean List
*
* @param sql
* @param clazz
* @return
* @throws Exception
*/
public List<T> getBeanList(String sql, Class<T> clazz) throws Exception {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
List<T> ts = new ArrayList<T>();
try {
conn = JdbcUtils.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
T t = null;
int[] pos = mapColumnsToProperties(rs, clazz);
while(rs.next()){
t = clazz.newInstance();
callSetter(t,pos,rs);
ts.add(t);
}
return ts;
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
/**
* 利用Java反射与内省(Introspector)机制进行装配
*
* @param t
* @param pos
* @param rs
* @throws Exception
*/
private void callSetter(T t, int[] pos, ResultSet rs) throws Exception {
ResultSetMetaData rsmd = rs.getMetaData();
PropertyDescriptor[] props = null;
BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass());
props = beanInfo.getPropertyDescriptors();
for(int i = 1; i<=rsmd.getColumnCount();i++){
if(pos[i]!= NOT_FOUND){
props[pos[i]].getWriteMethod().invoke(t, rs.getObject(i));
}
}
}
/**
* 找到resultset中每个值对应 bean中属性的位置
*
* @param rs
* @param clazz
* @return
* @throws SQLException
* @throws IntrospectionException
*/
private int[] mapColumnsToProperties(ResultSet rs,Class<T> clazz) throws SQLException, IntrospectionException{
ResultSetMetaData rsmd = rs.getMetaData();
int columnLength = rsmd.getColumnCount();
int[] columnsToProperties = new int[columnLength+1];
PropertyDescriptor[] props = null;
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
props = beanInfo.getPropertyDescriptors();
Arrays.fill(columnsToProperties,NOT_FOUND);
for(int col = 1; col <= columnLength; col++){
String columnName = rsmd.getColumnLabel(col);
if (null == columnName || 0 == columnName.length()) {
columnName = rsmd.getColumnName(col);
}
for(int i=0;i<props.length;i++){
if(props[i].getName().equalsIgnoreCase(columnName)){
columnsToProperties[col] = i;
break;
}
}
}
return columnsToProperties;
}
}
比较两种方式的执行效率:
package orm;
import java.util.List;
import model.User;
import org.junit.Test;
public class OrmTest {
@Test
public void ormTest() throws Exception{
long start = System.currentTimeMillis();
Orm<User> orm = new Orm<User>();
User user= (User) orm.getBean("SELECT userId ,department,division,email,employeeNo,name,passwordMD5,phone,position,state,type FROM tb_user",User.class);
System.out.println(user);
List<User> userList= orm.getBeanList("SELECT userId,department,division,email,employeeNo,name,passwordMD5,phone,position,state,type FROM tb_user",User.class);
for(User u : userList){
System.out.println(u);
}
System.out.println("耗时:"+(System.currentTimeMillis() - start)+"ms");
}
@Test
public void orm2Test() throws Exception{
long start = System.currentTimeMillis();
Orm2<User> orm2 = new Orm2<User>();
User user2 = orm2.getBean("SELECT userId,department,division,email,employeeNo,name,passwordMD5,phone,position,state,type FROM tb_user", User.class);
System.out.println(user2);
List<User> userList2= orm2.getBeanList("SELECT userId,department,division,email,employeeNo,name,passwordMD5,phone,position,state,type FROM tb_user",User.class);
for(User u : userList2){
System.out.println(u);
}
System.out.println("耗时:"+(System.currentTimeMillis() - start)+"ms");
}
}
结果如下:
User [userId=1, department=321, division=3213, email=321, employeeNo=321, name=321, passwordMD5=321, phone=321, position=321, state=321, type=21] User [userId=1, department=321, division=3213, email=321, employeeNo=321, name=321, passwordMD5=321, phone=321, position=321, state=321, type=21] User [userId=2, department=321, division=3213, email=321, employeeNo=321, name=321, passwordMD5=321, phone=321, position=321, state=321, type=21] 耗时:464ms User [userId=1, department=321, division=3213, email=321, employeeNo=321, name=321, passwordMD5=321, phone=321, position=321, state=321, type=21] User [userId=1, department=321, division=3213, email=321, employeeNo=321, name=321, passwordMD5=321, phone=321, position=321, state=321, type=21] User [userId=2, department=321, division=3213, email=321, employeeNo=321, name=321, passwordMD5=321, phone=321, position=321, state=321, type=21] 耗时:35ms
可见用内省机制改进后执行效率得到很大提高。