Java反射技术/简单ORM

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。


package com.royzhou.reflect;

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

public class ReflectTest {

private String id;

private String name;

public String property;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getProperty() {
return property;
}

public void setProperty(String property) {
this.property = property;
}

public ReflectTest() {
System.out.println("this is a constructor with no params!!!");
}

public ReflectTest(String param) {
System.out.println("this is a constructor with param :" + param
+ "!!!");
}

/**
* 创建对象
*
* @param clazz
* @param paramTypes:构造函数参数,如果为null表示调用无参函数
* @return
* @throws Exception
*/
public Object createObject(Class clazz, Class[] paramTypes)
throws Exception {
Object obj = null;
if (paramTypes == null) {
// 无参构造函数
obj = clazz.newInstance();
} else {
// 有参构造函数
Constructor con = clazz.getConstructor(paramTypes);
obj = con.newInstance("Test String param");
}
return obj;
}

/**
* 激活对象的某个方法
*
* @param obj
* @param methodName
* @throws Exception
*/
public void invokeMethod(Object obj, String methodName) throws Exception {
Method[] methods = obj.getClass().getDeclaredMethods(); // 拿到当前类的全部方法,包括私有的和公有的
methods = obj.getClass().getMethods(); // 拿到当前类以及父类的所有公有方法
for (Method m : methods) {
if (m.getName().equals(methodName)) {
m.invoke(obj, new Object[] {}); // 调用方法
}
}
}

public void getFileds(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields(); // 获取公有的属性
fields = obj.getClass().getDeclaredFields(); // 获取公有私有属性
for (Field f : fields) {
System.out.println(f.getName());
}
}

public void overload(String s) {
System.out.println("param is String :" + s);
}

public void overload(int i) {
System.out.println("param is int :" + i);
}

public void testInvoke() {
System.out.println("this is a method for invoke test!!!");
}

public static void main(String[] args) throws Exception {
ReflectTest rt = new ReflectTest();
Object obj = rt.createObject(ReflectTest.class, null);
System.out.println("--------------");
obj = rt.createObject(ReflectTest.class, new Class[] { String.class });
System.out.println("--------------");
rt.invokeMethod(obj, "testInvoke");
System.out.println("--------------");
Method m = obj.getClass().getMethod("overload", int.class);
m.invoke(obj, new Object[] { 1 });
System.out.println("--------------");
m = obj.getClass().getMethod("overload", String.class);
m.invoke(obj, new Object[] { "test overload String" });
System.out.println("--------------");
rt.getFileds(obj);
}
}



利用java的反射机制可以进行简单的ORM即对象关系映射
如下面代码:

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

public class ORMTest {

/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
User user = (User) getObject(
"select id as Id, name as Name from user where id=1",
User.class);
System.out.println(user);
}

public static List<Object> getObjects(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();
String[] colNames = getColNames(rs);

List<Object> objects = new ArrayList<Object>();
Method[] ms = clazz.getMethods();
while (rs.next()) {
Object object = clazz.newInstance(); //
for (int i = 0; i < colNames.length; i++) {
String colName = colNames[i];
String methodName = "set" + colName;
for (Method m : ms) {
if (methodName.equals(m.getName())) {
m.invoke(object, rs.getObject(colName));
break;
}
}
objects.add(object);
}
}
return objects;
} finally {
JdbcUtils.free(rs, ps, conn);
}
}

private static String[] getColNames(ResultSet rs) throws Exception {
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
String[] colNames = new String[count];
for (int i = 1; i <= count; i++) {
colNames[i - 1] = rsmd.getColumnLabel(i);
}
return colNames;
}

public static Object getObject(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();
String[] colNames = getColNames(rs);

Object object = null;
Method[] ms = clazz.getMethods();
if (rs.next()) {
object = clazz.newInstance();
for (int i = 0; i < colNames.length; i++) {
String colName = colNames[i];
String methodName = "set" + colName;
for (Method m : ms) {
if (methodName.equals(m.getName())) {
m.invoke(object, rs.getObject(colName));
break;
}
}
}
}
return object;
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
}


在这个简单的ORM中,利用Java的反射机制动态创建实例,不需要事先知道要生成什么对象或对象集合,只需要在调用的时候转型(当然也可以使用jdk1.5的泛型技术),使用m.invoke(object, rs.getObject(colName))方法动态设置实例的属性,注意,在这个例子中,user类必须是一个标准的Javabean,具有各个属性的setter/getter方法以及一个没有参数的构造函数,上面例子中使用sql的别名来实现动态调用对象的方法,(Hibernate使用配置文件.hbm.xml文件完成数据库字段到javabean的映射),只需要在写查询sql的时候指定好别名就可以完成javabean属性的设置。

假如有另外一个类 Product


public class Product {

private String id;

private String name;

private String manufatrue;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getManufatrue() {
return manufatrue;
}

public void setManufatrue(String manufatrue) {
this.manufatrue = manufatrue;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Product() {

}
}


这样我们在查询的时候只需要执行下面语句就可以获得封装好的Product对象/集合

Product product= (Product ) getObject("select id as Id, name as Name ,manufature as Manufature from product where id=1",Product .class);


这样的代码更具有动态性,不用每个查询写一个查询方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值