反射工具类ReflectionUtils

package net.pm.common.toolkit;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import net.pm.core.entities.db.Pmdept;
import net.pm.core.entities.db.Pmuser;

import org.apache.commons.lang3.StringUtils;

/**反射工具类
 * @author  shizeyuan
 *
 */
public abstract class ReflectionUtils {
	
	/**
	 * 缓存方法
	 */
	private static final Map<Class<?>, Method[]> METHODS_CACHEMAP = new HashMap<Class<?>, Method[]>();
	
	/**
	 * 反射 取值、设值,合并两个对象(Field same only )
	 * 
	 * @param from
	 * @param to
	 */
	public static <T> void copyProperties(T fromobj, T toobj, String... fieldspec) {
		for (String filename : fieldspec) {
			Object val = ReflectionUtils.invokeGetterMethod(fromobj, filename);
			ReflectionUtils.invokeSetterMethod(toobj, filename, val);
		}

	}
	
	public static void main(String[] args) {
		Pmdept dept1 = new Pmdept();
		dept1.setAddTime(new Date());
		dept1.setDeptCode("1code");
		dept1.setDeptDesc("1desc");
		dept1.setDeptName("1name");
		dept1.setId(1);
		
		Pmdept dept2 = new Pmdept();
		dept2.setId(2);
		Pmuser user = null;
		copyProperties(dept1, user = new Pmuser(), "id");
		
		System.out.println(user.getId());
		
	}
	
	/**调用Getter方法
	 * @param obj			对象
	 * @param propertyName  属性名
	 * @return 
	 */
	public static Object invokeGetterMethod(Object obj,String propertyName){
		String getterMethodName = "get"+StringUtils.capitalize(propertyName);
		return invokeMethod(obj, getterMethodName, null, null);
	}
	
	/**调用Setter方法,不指定参数的类型
	 * @param obj
	 * @param propertyName
	 * @param value
	 */
	public static void invokeSetterMethod(Object obj,String propertyName,Object value){
		invokeSetterMethod(obj, propertyName, value, null);
	}
	
	/**调用Setter方法,指定参数的类型
	 * @param obj
	 * @param propertyName
	 * @param value
	 * @param propertyType 为空,则取value的Class
	 */
	public static void invokeSetterMethod(Object obj,String propertyName,Object value,Class<?> propertyType){
		propertyType = propertyType != null ? propertyType : value
				.getClass();
		String setterMethodName = "set"+StringUtils.capitalize(propertyName);
		invokeMethod(obj, setterMethodName, new Class<?>[]{propertyType}, new Object[]{value});
	}
	
	
	/**直接调用对象方法,忽视private/protected修饰符
	 * @param obj
	 * @param methodName
	 * @param parameterTypes
	 * @param params
	 * @return 
	 */
	public static Object invokeMethod(final Object obj,
			final String methodName, final Class<?>[] parameterTypes,
			final Object[] args) {
		Method method = obtainAccessibleMethod(obj, methodName, parameterTypes);
		if (method == null) {
			throw new IllegalArgumentException(
					"Devkit: Could not find method [" + methodName
							+ "] on target [" + obj + "].");
		}
		try {
			return method.invoke(obj, args);
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**循环向上转型,获取对象的DeclaredMethod,并强制设置为可访问
	 * 如向上转型到Object仍无法找到,返回null
	 * 
	 * 用于方法需要被多次调用的情况,先使用本函数先取得Method,然后调用Method.invoke(Object obj,Object... args)
	 * @param obj
	 * @param methodName
	 * @param parameterTypes
	 * @return 
	 */
	public static Method obtainAccessibleMethod(final Object obj,
			final String methodName, final Class<?>... parameterTypes) {
		Class<?> superClass = obj.getClass();
		Class<Object> objClass = Object.class;
		for (; superClass != objClass; superClass = superClass.getSuperclass()) {
			Method method = null;
			try {
				method = superClass.getDeclaredMethod(methodName,
							parameterTypes);
				method.setAccessible(true);
				return method;
			} catch (NoSuchMethodException | SecurityException e) {
				// Method不在当前类定义,继续向上转型
			}
		}
		return null;
	}
	
	/**
	 * 不能确定方法是否包含参数时,通过方法名匹配获得方法
	 * @param obj
	 * @param methodName
	 * @return 
	 */
	public static Method obtainMethod(final Object obj,
			final String methodName){
		Class<?> clazz = obj.getClass();
		Method[] methods = METHODS_CACHEMAP.get(clazz);
		if (methods == null) { // 尚未缓存
			methods = clazz.getDeclaredMethods();
			METHODS_CACHEMAP.put(clazz, methods);
		}
		for (Method method : methods) {
			if (method.getName().equals(methodName))
				return method;
		}
		return null;
		
	}
	
	/**直接读取对象属性值
	 * 忽视private/protected修饰符,不经过getter函数
	 * @param obj
	 * @param fieldName
	 * @return 
	 */
	public static Object obtainFieldValue(final Object obj,final String fieldName){
		Field field = obtainAccessibleField(obj, fieldName);
		if(field == null){
			throw new IllegalArgumentException("Devkit: could not find field ["+fieldName+"] on target ["+obj+"]");
		}
		Object retval = null;
		try {
			retval = field.get(obj);
		} catch (IllegalArgumentException | IllegalAccessException e) {
			e.printStackTrace();
		}
		return retval;
		
	}
	
	/**直接设置对象属性值
	 * 忽视private/protected修饰符,不经过setter函数
	 * @param obj
	 * @param fieldName
	 * @param value
	 */
	public static void setFieldValue(final Object obj,final String fieldName,final Object value){
		Field field = obtainAccessibleField(obj, fieldName);
		if(field == null){
			throw new IllegalArgumentException("Devkit: could not find field ["+fieldName+"] on target ["+obj+"]");
		}
		try {
			field.set(obj, value);
		} catch (IllegalArgumentException | IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
	
	/**循环向上转型,获取对象的DeclaredField,并强制设为可访问
	 * 如向上转型Object仍无法找到,返回null
	 * @param obj
	 * @param fieldName
	 * @return 
	 */
	public static Field obtainAccessibleField(final Object obj,
			final String fieldName) {
		Class<?> superClass = obj.getClass();
		Class<Object> objClass = Object.class;
		for (; superClass != objClass; superClass = superClass.getSuperclass()) {
			try {
				Field field = superClass.getDeclaredField(fieldName);
				field.setAccessible(true);
				return field;
			} catch (NoSuchFieldException | SecurityException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
}

转载于:https://my.oschina.net/foggy/blog/57440

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值