修复Getter取值BUG

http://www.commontemplate.org
BUG: 在获取特殊Class(内部类)的属性时可能抛出异常, 将在下一版本(0.8.2)更新修复此bug.
重构前程序:
public class ClassUtils {

	/**
	 * 获取对象的属性值
	 * 
	 * @param object 对象实例
	 * @param property 属性名
	 * @return 属性的值
	 */
	public static Object getObjectProperty(Object object, String property) throws NoSuchMethodException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
		if (object == null)
			return null;
		try {
			return getClassGetter(object.getClass(), property).invoke(object, new Object[0]);
		} catch (NoSuchMethodException e) {
			return object.getClass().getField(property).get(object);
		}
	}

	/**
	 * 查找getXXX与isXXX的属性Getter方法
	 * 
	 * @param clazz 类元
	 * @param property 属性名
	 * @return 属性Getter方法
	 */
	public static Method getClassGetter(Class clazz, String property) throws NoSuchMethodException, SecurityException {
		Assert.assertNotNull(clazz, "class不能为空!");
		Assert.assertNotEmpty(property, "property不能为空!");
		property = property.trim();
		String upper = property.substring(0, 1).toUpperCase() + property.substring(1);
		try {
			Method getter = clazz.getMethod("get" + upper);
			Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
			return getter;
		} catch (NoSuchMethodException e1) {
			try {
				Method getter = clazz.getMethod("is" + upper);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			} catch (NoSuchMethodException e2) {
				Method getter = clazz.getMethod(property);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			}
		}
	}

}

其中: clazz . getMethod(), 在普通public的POJO下是正常的, 但对私有实现类, 内部类, 匿名类等都有问题.
测试:
Map map = new HashMap();
map.put("aa", "bb");
Map.Entry entry = (Map.Entry)map.entrySet().iterator().next();
Object key = ClassUtils.getObjectProperty(entry, "key");

此测试会抛出异常: can not access a member of class java.util.HashMap$Entry with modifiers "public"
这是因为 HashMap$Entry 是内部实现类, 其类修饰符不是public造成的.

重构如下: (加入getClassMethod)
public class ClassUtils {

	/**
	 * 获取对象的属性值
	 * 
	 * @param object 对象实例
	 * @param property 属性名
	 * @return 属性的值
	 */
	public static Object getObjectProperty(Object object, String property) throws NoSuchMethodException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
		if (object == null)
			return null;
		try {
			return getClassGetter(object.getClass(), property).invoke(object, new Object[0]);
		} catch (NoSuchMethodException e) {
			return object.getClass().getField(property).get(object);
		}
	}

	/**
	 * 查找getXXX与isXXX的属性Getter方法
	 * 
	 * @param clazz 类元
	 * @param property 属性名
	 * @return 属性Getter方法
	 */
	public static Method getClassGetter(Class clazz, String property) throws NoSuchMethodException, SecurityException {
		Assert.assertNotNull(clazz, "class不能为空!");
		Assert.assertNotEmpty(property, "property不能为空!");
		property = property.trim();
		String upper = property.substring(0, 1).toUpperCase() + property.substring(1);
		try {
			Method getter = getClassMethod(clazz, "get" + upper);
			Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
			return getter;
		} catch (NoSuchMethodException e1) {
			try {
				Method getter = getClassMethod(clazz, "is" + upper);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			} catch (NoSuchMethodException e2) {
				Method getter = getClassMethod(clazz, property);
				Assert.assertTrue(getter.getReturnType() != Void.class, "getter返回值类型不能为void!");
				return getter;
			}
		}
	}

	/**
	 * 获取类的方法 (保证返回方法的公开性)
	 * 
	 * @param clazz 类
	 * @param methodName 方法名
	 * @return 公开的方法
	 */
	public static Method getClassMethod(Class clazz, String methodName) throws NoSuchMethodException, SecurityException {
		Assert.assertNotNull(clazz, "class不能为空!");
		Assert.assertNotNull(methodName, "methodName不能为空!");
		try {
			return searchPublicMethod(clazz.getInterfaces(), methodName);
		} catch (NoSuchMethodException e1) {
			try {
				return searchPublicMethod(clazz.getClasses(), methodName);
			} catch (NoSuchMethodException e2) {
				return clazz.getMethod(methodName, new Class[0]);
			}
		}
	}

	// 查找公开的方法 (辅助方法)
	private static Method searchPublicMethod(Class[] classes, String methodName) throws NoSuchMethodException, SecurityException {
		if (classes != null && classes.length > 0) {
			for (int i = 0, n = classes.length; i < n; i ++) {
				Class cls = classes[i];
				if ((cls.getModifiers() & Modifier.PUBLIC) == 1) { // 首先保证类是公开的
					try {
						Method method = cls.getMethod(methodName, new Class[0]);
						if ((method.getModifiers() & Modifier.PUBLIC) == 1) // 再保证方法是公开的
							return method;
					} catch (NoSuchMethodException e) {
						// ignore, continue
					}
				}
			}
		}
		throw new NoSuchMethodException(); // 未找到方法
	}

}

你可能感兴趣的:(C++,c,C#,Access,commontemplate)