内省(Introspector) — sun公司的API
- 开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。
- 什么是Java对象的属性和属性的读写方法?
- 有一个getXxx()或setXxx()方法,那么xxx就是这个Java对象的属性。反过来讲,一个对象如果有一个getXxx()或setXxx()方法,那么这个类就一定有一个xxx属性。getXxx()是读,setXxx()是写。
- 内省访问JavaBean属性的两种方式:
- java.beans包提供了内省的API。
- 通过PropertyDescriptor类操作Bean的属性
- 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter方法,然后通过反射机制来调用这些方法。
- java.beans包提供了内省的API。
package cn.mengmei.introspector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import org.junit.Test;
public class Demo1 {
//通过内省(Introspector)API 操作 javabean 的某一个属性。
@Test
public void test1() throws Exception {
Person p = Person.class.newInstance();
PropertyDescriptor pd = new PropertyDescriptor("name", Person.class);
Method method = pd.getWriteMethod(); //得到此方法:setName()
method.invoke(p, "meimei");
method = pd.getReadMethod(); //得到此方法:getName()
String result = (String)method.invoke(p, null);
System.out.println(result);
}
//通过内省(Introspector)API 操作 javabean 的 所有属性。
@Test
public void test2() throws Exception {
BeanInfo info = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] pds = info.getPropertyDescriptors();
for(PropertyDescriptor pd : pds){
System.out.println(pd.getName()); //class name age
//由于Person类是Object的子类,继承了Object的所有方法。
//因为Object类有一个getClass()方法,所以就默认有一个class属性。
//所以这里显示:Person类有三个属性:class、name 和 age。
//接下来得到每一个属性的get、set方法就又是上面那段代码了。
}
}
}
package cn.mengmei.introspector;
public class Person {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
由于sun公司这套API操作javabean属性还是有点繁琐。所以就由开源组织又开发了一套API来操作javabean的属性,这套API的名字叫BeanUtils。
Apache开源组织 - beanutils工具包 (常用)
- Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。
- BeanUtils工具包的常用类:
- BeanUtils
- PropertyUtils
- ConvertUtils.regsiter(Converter convert, Class clazz)
- 自定义转换器
commons-beanutils-1.8.0.jar 包 在工作的过程中依赖于日志包:commons-logging.jar ,同样导入。
package cn.mengmei.beanutils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; //这里容易出错!我真是....。是Date ,在自动import的时候,变成了sql.Date;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.junit.Test;
public class Demo1 {
@Test
public void test1() throws Exception {
Person p = new Person();
BeanUtils.setProperty(p, "name", "hanmeimei"); //设置p对象的name属性的值为hanmeimei
String result = BeanUtils.getProperty(p, "name"); //获取p对象的name属性的值。
System.out.println(result);
}
@Test
public void test2() throws Exception {
//从客户端接收到这些信息都是字符串的。
String name = "liugang";
String age = "23";
String email = "liugang@sina.com";
String password = "123";
String birthday = "1980-10-18";
Person p = new Person();
//注册一个转换器
ConvertUtils.register(new DateLocaleConverter(), Date.class); //当遇到将字符串转换成Date类型的时候,就使用(DateLocaleConverter)本地环境日期转换器
//利用BeanUtils工具为p对象的属性设置值。
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age); //BeanUtils可以自动将字符串转成8种基本数据类型。
BeanUtils.setProperty(p, "email", email);
BeanUtils.setProperty(p, "password", password);
BeanUtils.setProperty(p, "birthday", birthday); //由于Date不是基本数据类型,转换的时候需要调用转换器。
System.out.println(p.getName());
System.out.println(p.getAge());
System.out.println(p.getEmail());
System.out.println(p.getPassword());
System.out.println(p.getBirthday());
}
//自定义转换器
@Test
public void test3() throws Exception {
String birthday = "1980-10-18";
Person p = new Person();
ConvertUtils.register(new Converter() {
@Override
public Object convert(Class type, Object value) {
if(value == null){
return null;
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse((String) value);
} catch (ParseException e) {
throw new ConversionException(e);
}
return date;
}
}, Date.class);
BeanUtils.setProperty(p, "birthday", birthday);
System.out.println(p.getBirthday());
}
}
DateLocaleConverter 是 Converter 的已知实现类。
在用到转换器的时候先看看 Converter 的已知实现类里有没有可以用到的,如果没有再自己定义。
package cn.mengmei.beanutils;
import java.util.Date;
public class Person {
private String name;
private int age;
private String email;
private String password;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}