`
royzhou1985
  • 浏览: 249898 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Java反射技术/简单ORM

    博客分类:
  • Java
阅读更多
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);


这样的代码更具有动态性,不用每个查询写一个查询方法
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics