为什么要学内省?
•开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。
l什么是Java对象的属性和属性的读写方法?
l内省访问JavaBean属性的两种方式:
•通过PropertyDescriptor类操作Bean的属性
•通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter方法,然后通过反射机制来调用这些方法。
package com.gui.test;
import java.util.Date;
public class Dog {
private String name;
private int age;
private String color;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
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 String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
package com.gui.test;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Before;
import org.junit.Test;
public class DogTest {
Dog dog;
@Before
public void before() throwsClassNotFoundException, InstantiationException,IllegalAccessException {
Class clazz =Class.forName("com.gui.test.Dog");
dog = (Dog)clazz.newInstance();
}
@Test
public void testGetAllNames() throwsIntrospectionException {
BeanInfo info = Introspector.getBeanInfo(Dog.class, Object.class);
PropertyDescriptor[] pds =info.getPropertyDescriptors();
for (PropertyDescriptor pd :pds) {
System.out.println(pd.getName());
}
}
@Test
public void testGetAge() throwsIntrospectionException, IllegalArgumentException,IllegalAccessException, InvocationTargetException {
PropertyDescriptor pd= new PropertyDescriptor("age", Dog.class);
System.out.println(pd.getName());
System.out.println(pd.getPropertyType());
Method method =pd.getWriteMethod();
method.invoke(dog,33);
method =pd.getReadMethod();
System.out.println(method.invoke(dog));
}
}
Sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils
Beanutils工具包的常用类:
BeanUtils
PropertyUtils
ConvertUtils.regsiter(Converter convert, Class clazz)
自定义转换器
开发之前 要先引入 commons-beanutils-1.8.0.jar 和 commons-logging.jar包
package com.gui.test;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
importorg.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.junit.Before;
import org.junit.Test;
public class BeanUtilTest {
Dog dog;
@Before
public void before() throwsClassNotFoundException, InstantiationException,IllegalAccessException {
Class clazz =Class.forName("com.gui.test.Dog");
dog = (Dog)clazz.newInstance();
}
@Test
public void test1() throwsIllegalAccessException, InvocationTargetException,NoSuchMethodException {
BeanUtils.setProperty(dog,"name", "kitty");
System.out.println(BeanUtils.getProperty(dog,"name"));
}
@Test
public void test2() throwsIllegalAccessException, InvocationTargetException,NoSuchMethodException {
ConvertUtils.register(newDateLocaleConverter(), Date.class);//可自己实现Converter接口 日期转换
BeanUtils.setProperty(dog,"name", "kitty");
BeanUtils.setProperty(dog,"birthday", "2011-01-01");
System.out.println(BeanUtils.getProperty(dog,"name"));
System.out.println(BeanUtils.getProperty(dog,"birthday"));
}
@Test
public void test3() throwsIllegalAccessException, InvocationTargetException,NoSuchMethodException {
//为了让日期赋到bean的birthday属性上,我们给beanUtils注册一个日期转换器
ConvertUtils.register(newConverter(){// 系统自动支持8种基本类型转换
publicObject convert(Class type, Object value) {
if(value==null){
returnnull;
}
if(!(valueinstanceof String)){
thrownew ConversionException("仅string类型的转换!!");
}
Stringstr = (String) value;
if(str.trim().equals("")){
returnnull;
}
SimpleDateFormatdf = new SimpleDateFormat("yyyy-MM-dd");
try{
returndf.parse(str);
}catch (ParseException e) {
thrownew RuntimeException(e); //异常链不能断
}
}
}, Date.class);
Map map =new HashMap();
map.put("name", "aaa");
map.put("color", "red");
map.put("age", "23");
map.put("birthday","1980-09-09");
ConvertUtils.register(newDateLocaleConverter(), Date.class);
BeanUtils.populate(dog,map); //用map集合中的值,填充bean的属性
System.out.println(BeanUtils.getProperty(dog,"name"));
System.out.println(BeanUtils.getProperty(dog,"color"));
System.out.println(BeanUtils.getProperty(dog,"age"));
System.out.println(BeanUtils.getProperty(dog,"birthday"));
}
}