=============================================================================
内省(Introspector类) —> JavaBean
-----------------------------------------------------------------------------
一、为什么要学内省?
开发框架时,经常需要使用java对象的属性来封装程序的数据,
每次都使用 反射技术 完成此类操作过于麻烦,所以SUN公司开发了一套API,专门用于操作java对象的属性。
-----------------------------------------------------------------------------
二、什么是JavaBean和属性的读写方法?
bean就是类,javabean就是java类。
-----------------------------------------------------------------------------
三、通过内省技术访问(java.beans包提供了内省的API)JavaBean的两种方式:
1、 通过 PropertyDescriptor类 操作 Bean 的属性
2、 通过 Introspector类 获得Bean对象的 BeanInfo,BeanInfo将一个类的所有属性进行了封装。
然后通过 BeanInfo对象 来获取属性的描述器对象 PropertyDescriptor,
通过这个属性描述器对象就可以获取某个属性对象,然后通过反射机制来调用getter/setter方法。
(注意:在反射里面,成员变量叫字段,成员方法(特指getter/setter方法)叫属性)
PropertyDescriptor顾名思义,就是属性描述之意。它通过反射快速操作JavaBean的getter/setter方法。
重要方法:
Method getWriteMethod() 获取setter方法,返回Method对像
Method getReadMethod() 获取getter方法,返回Method对像
--------------------------------------
Student stu = new Student();
// 得到指定的属性对象
PropertyDescriptor pd = new PropertyDescriptor("name", Student.class);
Method setter = pd.getWriteMethod(); // 得到setter方法:setName()
setter.invoke(stu, "tom");
Method getter = pd.getReadMethod(); // 得到getter方法:getName()
System.out.println(getter.invoke(stu, null));
--------------------------------------
看上面的代码思考一个问题:既然我已经实例化了Student类,为什么不直接调用它的setName方法呢?
其实正确的用法应该是:与Student类完全的解耦。(就是说我写的代码中不会出现学生类了,学生类放在配置文件里面)
Class cls = Class.forName("cn.itcast.Student");
Object obj = cls.newInstance();
PropertyDescriptor pd = new PropertyDescriptor("name", cls);
Method m = pd.getWriterMethod();
m.invode(obj, "tom");
m = pd.getReadMethod();
System.out.println((String) m.invoke(obj));
-----------------------------------------------------------------------------
四、Beanutils工具包
Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,
因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。
Beanutils工具包的常用类:
BeanUtils
PropertyUtils
ConvertUtils.regsiter(Converter convert, Class clazz)
自定义转换器
--------------------------------------
需要依赖两个jar包:
commons-beanutils-1.8.3.jar
commons-logging-1.1.1.jar
--------------------------------------
示例:
Student stu = new Student();
BeanUtils.setProperty(stu, "name", "张三"); // 给属性赋值
String s = BeanUtils.getProperty(stu, "name"); // 获取属性值
System.out.println(s);
--------------------------------------
Student stu = new Student();
BeanUtils.setProperty(stu, "age", "18"); // BeanUtils默认支持8种基本数据类型,自动转换
String s = BeanUtils.getProperty(stu, "age");
System.out.println(s);
--------------------------------------
Student stu = new Student();
// 注册类型转换器
ConvertUtils.register(new DateLocaleConverter(), Date.class);
BeanUtils.setProperty(stu, "birthday", "1990-11-12"); // 给属性赋值
String s = BeanUtils.getProperty(stu, "birthday");
System.out.println(s);
--------------------------------------
Student stu = new Student();
// 注册类型转换器
ConvertUtils.register(new Converter() {
@Override
public Object convert(Class type, Object value) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
if (value instanceof String) {
String v = (String) value;
try {
return sdf.parse(v);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
return null;
}
}, Date.class);
BeanUtils.setProperty(stu, "birthday", "1995-11-12"); // 给属性赋值
String s = BeanUtils.getProperty(stu, "birthday");
System.out.println(s);
--------------------------------------
Map m = new HashMap();
m.put("name", "张三"); // key名一定要与对象中的变量名一致
m.put("age", "18"); // key名一定要与对象中的变量名一致
m.put("birthday", "1992-05-12"); // key名一定要与对象中的变量名一致
Student stu = new Student();
// 注册类型转换器
ConvertUtils.register(new DateLocaleConverter(), Date.class);
BeanUtils.populate(stu, m); // 将Map属性自动填充Bean中,这句话,后期学到框架的时候经常用到
System.out.println(stu.getName());
=============================================================================