内省、beanutils-工具包及应用

为什么要学内省?
开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。

什么是Java对象的属性和属性的读写方法?
内省访问JavaBean属性的两种方式:
通过PropertyDescriptor类操作Bean的属性
通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。

内省是 Java 语言对 Bean 类属性的一种缺省处理方法。例如类 A 中有属性 name, 可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这是默认的规则。 Java 中提供了一套 API 来访问某个属性的 getter/setter 方法。
一般的做法是通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法

内省应用代码:

package com.hbsi.introspector;

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.Test;

public class Demo1 {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub

 }
 //通过内省获取person bean的所有属性
 @Test
 public void test1() throws Exception{
  BeanInfo bi=Introspector.getBeanInfo(Person.class,Object.class);
  
  PropertyDescriptor[] pds=bi.getPropertyDescriptors();
  
  for(PropertyDescriptor pd:pds){
   String name=pd.getName();
   System.out.println(name);
  }
  
 }
 
 
 //通过内省给person的name属性赋值:abc   setName("abc")
 @Test
 public void test2() throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
  
  Person p=new Person();
  
  BeanInfo bi=Introspector.getBeanInfo(Person.class);
  
  PropertyDescriptor[] pds=bi.getPropertyDescriptors();
  
  for(PropertyDescriptor pd:pds){
   String name=pd.getName();
   if(name.equals("name")){
    Method m=pd.getWriteMethod();
    m.invoke(p, "abc");
   }
  }
  System.out.println(p.getName());
 }
 
 
 //通过PropertyDescriptor类操作Bean的属性  name属性赋值:ffff   setName("abc")
 
 @Test
 public void Test3() throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
  
  Person p=new Person();
  
  PropertyDescriptor pd=new PropertyDescriptor("name", p.getClass());
  
  Method m=pd.getWriteMethod();
  
  m.invoke(p,"ffff");
  
  System.out.println(p.getName());
  
 }
 
 @Test
 public void Test4() throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
  Person p=new Person();
  p.setName("abcdef");
  
  PropertyDescriptor pd=new PropertyDescriptor("name",p.getClass());
  
  Method m=pd.getReadMethod();
  
  String str=(String)m.invoke(p, null);
  System.out.println(str);
 }

}

package com.hbsi.introspector;

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 String getAb(){
  return null;
 }
 
 

}

内省—beanutils工具包

Sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils
Beanutils工具包的常用类:
BeanUtils
PropertyUtils
ConvertUtils.regsiter(Converter convert, Class clazz)
自定义转换器

一个实例代码:

package com.hbsi.beanutils;

import java.lang.reflect.InvocationTargetException;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.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 IllegalAccessException, InvocationTargetException{
  Person p=new Person();
  BeanUtils.setProperty(p,"name","张三");
  System.out.println(p.getName());
  
 }
 
 //beanutils工具对基本数据类型可以自动转换类型
 @Test
 public void test2() throws IllegalAccessException, InvocationTargetException{
  //自定义转换器
  ConvertUtils.register(new Converter(){

   @Override
   public Object convert(Class type, Object value) {
    
    if(value==null){
     return null;
    }
    if(!(value instanceof String)){
     throw new ConversionException("只能转String数据");
    }
    String s=(String)value;
    
    if(s.trim().equals("")){
     return null;
    }
    
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
    try {
     Date d=sdf.parse(s);
     return d;
    } catch (ParseException e) {
     // TODO Auto-generated catch block
     throw new ConversionException("转换错误");
    }   
   }  
  }, Date.class);
  
  
  
  String name="张三";
  String age="23";
  String birthday="     ";
  
  Person p=new Person();
  BeanUtils.setProperty(p,"name",name);
  BeanUtils.setProperty(p,"age",age);
  BeanUtils.setProperty(p,"birthday",birthday);
  
  System.out.println(p.getName()+"..."+p.getAge()+"...");
  
  
 }
 //使用beanUtils中的转换器完成数据转换
 @Test
 public void test3() throws IllegalAccessException, InvocationTargetException{
  
  ConvertUtils.register(new DateLocaleConverter(), Date.class);
  
  Person p=new Person();
  BeanUtils.setProperty(p,"birthday","   ");
  //System.out.println(p.getBirthday());
  
 }
 

}

/*class MyConver implements Converter{

 @Override
 public Object convert(Class arg0, Object arg1) {
  // TODO Auto-generated method stub
  return null;
 }
 
}*/

package com.hbsi.beanutils;

import java.util.Date;

public class Person {
 
 private String name;
 private int age;
 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 getAb(){
  return null;
 }
 
 

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值