内省(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*/ public class Orm2 { private static final int NOT_FOUND = -1; /** * 获得映射数据库后的一个装配好的实体对象bean * * @param sql * @param clazz * @return * @throws Exception */ public T getBean(String sql, Class 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 getBeanList(String sql, Class clazz) throws Exception { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; List ts = new ArrayList (); 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 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 比较两种方式的执行效率: 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(); Ormorm = new Orm (); 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 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 orm2 = new Orm2 (); 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 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
可见用内省机制改进后执行效率得到很大提高。