一:内省的概念
1:内省是反射的一种特例,由于在反射中频繁的操作javabean,所以为了方便反射
javabean,sun公司开发出一套API提高效率。
2:javaBean,就是用来封装客户端请求数据,有字段、get、set方法的对象,javaBean对象的属性有getXXX方法
决定。
二:内省访问JavaBean
1:定义javaBean
public class Person {
private String name;
private int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public double getSalary() {
return 12000.0;
}
}
2:访问javaBean对象
a:获取所有的属性
@Test
// 获取所有的属性
public void test1() throws Exception {
BeanInfo bi = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
System.out.println(pd.getName());
}
}
运行结果:
age
class
name
salary
其中age ,name是定义的成员变量,salary是getSlary()方法定义的,class是因为Person继承了Object类,
所以也继承了Object的方法getClass();
要想得到自己定义的类,可以使用getBeanInfof(Person.class,Object.class)方法,如下:
@Test
// 获取所有的属性
public void test1() throws Exception {
// BeanInfo bi = Introspector.getBeanInfo(Person.class);
BeanInfo bi = Introspector.getBeanInfo(Person.class, Object.class);
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
System.out.println(pd.getName());
}
}
运行结果:
age
name
salary
b:操作属性
@Test
// 操作属性
public void test2() throws Exception {
Person p = new Person();
PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);
// 获取getxxx()方法
Method m = pd.getWriteMethod();
m.invoke(p, 27);
// 获取setxxx()方法
m = pd.getReadMethod();
System.out.println(m.invoke(p, null));
}
c:获取当前属性的类型
// 获取当前属性的类型
public void test3() throws Exception {
PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);
System.out.println(pd.getPropertyType());
}
运行结果:
int
三:BeanUtils工具类的使用
beanUtils工具是apache基金会为了方便操作javaBean类,开发的一套API,在实际的开发中使用多于内省。
1:使用beanUtils设置属性的值
@Test
// 使用beanutils设置属性
public void test01() throws Exception {
Person p = new Person();
BeanUtils.setProperty(p, "age", 27); // 设置age为27
System.out.println(p.getAge());
}
2:beanUtils内部有类型自动转换的机制,String类型可以转换为8种基本数据类型,如下:
@Test
public void test02() throws Exception {
Person p = new Person();
String name = "Jack";
String age = "27";
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age); // 这里String类型转换为int类型
System.out.println(p.getName() + ":" + p.getAge());
}
本来Person类中age为int类型,但是String类型的age直接赋给了bean,但是转换仅限于8种基本数据类型。
3:如果是其他的类型,则转换会失败,如下Date类型,String转换是就会报错:
@Test
public void test03() throws Exception {
Person p = new Person();
String name = "Jack";
String age = "27";
String birthday = "2010-10-02";
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age); // 这里String类型转换为int类型
BeanUtils.setProperty(p, "birthday", birthday); // 这里会报错,因为String类型自动转化仅限于8种基本类型
System.out.println(p.getName() + ":" + p.getAge() + ":"
+ p.getBirthday());
}
异常如下:
4:自定义String到Date的转化器
@Test
public void test04() throws Exception {
Person p = new Person();
String name = "Jack";
String age = "27";
String birthday = "2010-10-02";
ConvertUtils.register(new Converter() { @Override
public Object convert(Class arg0, Object value) {
if (value == null) {
return null;
}
if (!(value instanceof String)) {
throw new ConversionException("转换异常!");
}
String str = (String) value;
if (str.trim().equals("")) {
return null;
}
// 排除以上情况,开始转换
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.parse(str);
} catch (ParseException e) {
throw new RuntimeException(e);
}
} }, Date.class); // 将转换器里定义转换方法
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age); // 这里String类型转换为int类型
BeanUtils.setProperty(p, "birthday", birthday); // 这里会报错,因为String类型自动转化仅限于8种基本类型
System.out.println(p.getName() + ":" + p.getAge() + ":"
+ p.getBirthday());
}
转换成功!
5:使用BeanUtils定义的转化器
@Test
public void test05() throws Exception {
Person p = new Person();
String name = "Jack";
String age = "27";
String birthday = "2010-10-02";
ConvertUtils.register(new DateLocaleConverter(), Date.class); // 将转换器里定义转换方法
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age); // 这里String类型转换为int类型
BeanUtils.setProperty(p, "birthday", birthday); // 这里会报错,因为String类型自动转化仅限于8种基本类型
System.out.println(p.getName() + ":" + p.getAge() + ":"
+ p.getBirthday());
}
但是这里有几个问题:
a:导包错误,导入java.util.Date,而不是java.sql.Date,否则报错,如下:
b:导入的commons-beanUtils.jar版本不对,建议commons-beanUtils-1.9.2.jar或者commons-beanUtils-1.9.2.jar都可以,
否则报错如下:
c:但是使用自定义的转换器有缺点,就是当日期字符串为空时,它不能判断,仍然后进行转换,异常如下:
但是自定义的转换器是没有这个问题的。
6:将map里存储的key-value封装到bean里面
@Test
public void test06() throws Exception {
Person p = new Person();
Map<String, Object> map = new HashMap<String, Object>();
String name = "Jack";
String age = "27";
String birthday = "2010-10-02";
ConvertUtils.register(new DateLocaleConverter(), Date.class);
map.put("name", name);
map.put("age", age);
map.put("birthday", birthday);
BeanUtils.populate(p, map);
System.out.println(p.getName());
System.out.println(p.getAge());
System.out.println(p.getBirthday());
}
以上代码均已经验证!