Java基础之内省

内省是与反射密切相关的
javabean是一种特殊的java类,它的全部或者部分方法的名称是按约定的规则(要么是set打头要么是get打头)确定的,javabean属性的名称是根据set和get方法的名称来确定的,不是根据私有成员变量,并且set方法没有返回值,get方法没有参数。
gettime->time
setTime->Time
getCPU->CPU
属性名是把set/get去掉之后,如果第二个字母是小写的,则把首字母也变成小写的,如果第二个字母是大写,则首字母保持原样;
JDK中提供了对javabean进行操作的一些API,这套API称为内省。内省的功能也可以用反省来完成,只不过反省太原生,有点麻烦,所以提供内省,本质上还是原来反射那一套。

对javabean的内省操作:

 

public class IntrospectTest {

	public static void main(String[] args) throws Exception {
		ReflectPoint pt1 = new ReflectPoint(3, 5);
		String propertyName = "x";
		// 普通反射方式获取属性x的值过程:x->X->getX->MethodGetX->
		Object retVal = getProperty(pt1, propertyName);
		System.out.println(retVal);// 3

		Object val = 7;
		setProperty(pt1, propertyName, val);
		// 使用BeanUtils工具包操作javabean,BeanUtils把set/get属性的值都是当作字符串来操作的
		System.out.println(BeanUtils.getProperty(pt1, "x"));// 7
		System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName());// java.lang.String
		BeanUtils.setProperty(pt1, "x", "9");// x属性本来是整型的
		System.out.println(pt1.getX());// 9
		// 支持属性的级联操作,要先为ReflectPoint添加Date birthday属性,并且要赋初值
		BeanUtils.setProperty(pt1, "birthday.time", "111");
		System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));// 111
		// BeanUtils.describe把javabean转换成map,BeanUtils.populate把map的东西填充到javabean里面去
		// 新技术是为了解决老问题的,不是新问题,是因为用老技术解决老问题太繁琐
		// PropertyUtils是以属性本身的类型来进行操作javabean(即不进行类型转换),
		// 如果使用BeanUtils进行类型转换不准确或出错可以尝试PropertyUtils
		PropertyUtils.setProperty(pt1, "x", 9);
		System.out.println(PropertyUtils.getProperty(pt1, "x"));// 9
		System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName());// java.lang.Integer

	}

	private static void setProperty(ReflectPoint pt1, String propertyName, Object val) throws IntrospectionException, IllegalAccessException, InvocationTargetException {
		PropertyDescriptor pd2 = new PropertyDescriptor(propertyName, pt1.getClass());
		Method methodSetX = pd2.getWriteMethod();
		methodSetX.invoke(pt1, val);
	}

	private static Object getProperty(Object pt1, String propertyName) throws IntrospectionException, IllegalAccessException, InvocationTargetException {
		// PropertyDescriptor pd = new PropertyDescriptor(propertyName,
		// pt1.getClass());// 必须为属性名设置set/get方法
		// Method methodGetX = pd.getReadMethod();
		// Object retVal = methodGetX.invoke(pt1);

		// BeanInfo表示把java类当成javabean看的结果所封装的信息
		// 张老师最早用的就是下面这种方式,后来发现上面的那种简便的方式
		BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());// getClass()比.class更通用
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		Object retVal = null;
		for (PropertyDescriptor pd : pds) {
			System.out.println("test " + pd.getName());
			if (pd.getName().equals(propertyName)) {
				Method methodGetX = pd.getReadMethod();
				retVal = methodGetX.invoke(pt1);
				break;
			}
		}

		return retVal;
	}

}

 

 

 

 

 

posted @ 2016-10-22 11:47  john8169  阅读(112)  评论(0编辑  收藏  举报