内省
基本概念
为什么要学习内省?
>开发框架是,经常需要使用java对象的属性来封装程序的数据,每次都是用反射技术完成此类操作过于麻烦,所以sun开发了一套api,专门用于操作java对象的属性
什么是java对象的属性和属性的读写方法?
>
作用:
>简化反射对于java属性封装的操作
javabean的基本概念:
属性:
拥有get/set方法的
>package test_introspector;
public class Person {//这个类可以被称为javabean——拥有什么属性取决于什么东西拥有get/set方法——
//这个有五个属性——AB,age.password,name,Object中的getclass属性中的class属性。
private String password;
private int age;
private String name;//字段—
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAB(){
return null;
}
}
使用
使用内省获取javabean的属性
package test_introspector;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import org.junit.Test;
public class Demo1 {
@Test
public void test1() throws IntrospectionException{
BeanInfo info=Introspector.getBeanInfo(Person.class);//拿到person的所有属性
PropertyDescriptor[]pda= info.getPropertyDescriptors();//拿到属性描述器
for(PropertyDescriptor p:pda){
System.out.println(p.getName());
}
}
}
使用内省操作bean的指定属性:
public void test2() throws Exception{
Person p = new Person();
PropertyDescriptor pd= new PropertyDescriptor("age",Person.class);//拿到属性描述器
//得到属性的写方法,为属性赋值
Method method = pd.getWriteMethod();
method.invoke(p, 45);
//传统方法
System.out.println(p.getAge());
//内省方法___________重要,有问题!!!
method=pd.getReadMethod();
System.out.println(method.invoke(p, null));
}
获取当前操作的属性类型——有问题!!!
public void tes34() throws Exception{
Person p = new Person();
PropertyDescriptor pd= new PropertyDescriptor("age",Person.class);//拿到属性描述器
System.out.println(pd.getPropertyType());
}
beanutils框架
操作字符串(分为可自动转换的8种类型,和需要注册转换的非8种基本类型)
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
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.junit.Test;
import test_introspector.Person;
//使用beanUtils操纵bean的属性(第三方——
public class Demo1 {
//情景:这个人的数据由用户表单提交
@Test
public void tes21() throws Exception{
String name = "aaaa";
String birthday ="1980-09-09";
//String password ="1234";
//为了让日期到bean的birthday属性上,我们给beanutils注册了一个日期转换器
ConvertUtils.register(new Converter(){
@Override
public Object convert(Class arg0, Object arg1) {
// TODO Auto-generated method stub
if(arg1==null){
return null;
}
if(!(arg1 instanceof String)){
throw new ConversionException("仅支持string类型的转换");
}
String str = (String)arg1;
if(str.trim().equals("")){
return null;
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-NN-dd");//格式转换
try {
return df.parse(str);
} catch (ParseException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e); //写e:异常链——让异常链不断!!!——原来的信息被封装进去
}
}
}, Date.class);
Person p = new Person();
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "birthday", birthday);//仅支持8种类的数据类型自动转换
System.out.println(p.getName());
System.out.println(p.getBirthday());
}
}
实现2(有bug,无法实现检查)
在convertUtils.register传入中,直接传入一个localdata的类 ,好处:不用实现类。坏处:不健壮
将map集合填充到bean中——有问题!!
public void test5() throws Exception, Exception{
Map map = new HashMap();
map.put("name", "aaa");
map.put("password", "123");
map.put("age", "23");
map.put("birthday", "1980-09-09");
ConvertUtils.register(new DateLocaleConverter(), Date.class);
Person bean = new Person();
BeanUtils.populate(bean, map);
System.out.println(bean.getName());
System.out.println(bean.getBirthday());
//名字必须和bean中相同