使用内省封装数据到对象中

读取txt中的数据并使用反射创建对象封装程序数据

package javaee_review.读取txt中的数据并使用反射创建对象封装程序数据;


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;


/*
  需求:编写一个工厂方法根据配置文件的内容,返回对应的对象,并且把对象要有对应的属性值
  
*/


public class test05 {
public static void main(String[] args) throws Exception {
String s = newInstance().toString();
System.out.println(s);
}
//根据配置文件的内容生产对象的对象并且把对象的属性值封装到对象中。
    public static Object newInstance() throws Exception {
BufferedReader b = new BufferedReader(new FileReader("obj.txt"));//路径从当前项目
     String className = b.readLine();//读取配置文件获取到完整的类名                                         
           Class clazz = Class.forName(className);  
         /*      //通过class对象获取到无参的构造方法
            Constructor c = clazz.getConstructor(null);
            //创建对象
            Object o = c.newInstance(null);*/
            //读取属性值
            Object o = clazz.newInstance(); 
           String line = null;
            while ((line = b.readLine())!=null) {
                   String[] datas = line.split("=");
                  //通过属性名获取到对应的Field对象
                   Field field = clazz.getDeclaredField(datas[0]);
                 if (field.getType() == int.class) {
 field.set(o, Integer.parseInt(datas[1]));
} else {
field.set(o,datas[1]);

}
     return o;
    }     
   


}




开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,

所以sun公司开发了一套API【内省Introspector】,专门用于操作java对象的属性。


//内省是一个变态的反射

//通过内省封装数据到对象中

第一:封装指定属性值

public class test {


@Test
public void testProprety() throws Exception {
Person p = new Person();
// 获取指定属性的属性描述器
PropertyDescriptor pDescriptor = new PropertyDescriptor("id",
Person.class);
// 获取属性对应的set和get方法进行设置和获取属性值
Method method = pDescriptor.getWriteMethod();// 获取set方法
method.invoke(p, 110);
Method method2 = pDescriptor.getReadMethod();
System.out.println(method2.invoke(p, null));
PropertyDescriptor descriptor = new PropertyDescriptor("name",
p.getClass());
Method method3 = descriptor.getWriteMethod();
method3.invoke(p, "徐丽芬");
Method readMethod = descriptor.getReadMethod();
System.out.println(readMethod.invoke(p, null));

}

第二:

//方法描述器
@Test
public void testMethod() throws Exception {
Person p = new Person();
              MethodDescriptor descriptor = new MethodDescriptor(method, parameterDescriptors);
              MethodDescriptor descriptor2 =  new MethodDescriptor(method);
    //方法的参数描述器
              descriptor.getParameterDescriptors();
    

}

第三:

//使用内省类获取所有方法描述器
@Test
 public void testAllProperty() throws Exception{
//Introspector ,获取内省类
 BeanInfo bean = Introspector.getBeanInfo(Person.class);
   //通过内省类获取所有属性描述器
 MethodDescriptor[] method = bean.getMethodDescriptors();
     for (MethodDescriptor methodDescriptor : method) {
System.out.println(methodDescriptor.getDisplayName());

}
}

第四:

通过Introspector类获得Bean对象的BeanInfo,然后通过BeanInfo 来获取属性的描述器(PropertyDescriptor ),

通过这个属性描述器就可以获取某个属性对应的 getter/setter方法,然后通过反射机制来调用这些方法。

//使用内省类获取所有属性的描述器
@Test
public void testAllProperty() throws Exception{
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] prDescriptors = beanInfo.getPropertyDescriptors();
   System.out.println(prDescriptors.length); 
for (PropertyDescriptor propertyDescriptor : prDescriptors) {
       Method writeMethod = propertyDescriptor.getWriteMethod();
      
       System.out.println(writeMethod);
    
       Method readMethod = propertyDescriptor.getReadMethod();
      System.out.println(readMethod);
      
        
}
}
}


内省API存在的问题: sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils。

如下

package javaee_review.Beanutls封装对象数据到对象;


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.ConvertUtils;
import org.apache.commons.beanutils.Converter;


/*beanutils主要解决的问题:把对象的属性数据封装到对象中去
 *beanutils技术只不过把我们内省那一套技术封装起来了,用起来更加方便,底层
 *还是使用的内省的set和get方式
 *
 * //注意导入commons-beanutils-1.8.0.jar,还要导入beanutils依赖的日志工具:commons-logging.jar工具包
 * 
 * beanUtils的好处:
 * 1.beanutils设置属性值时,基本的数据类型会帮我们自动转换
 * 2.因为底层使用的内省,所以beanutils底层也是依赖于set和get方法设置和获取属性值
 * 3.如果是引用类型的话,一般需要我们自己定义一个类型转换器
 * */


public class BeanUtil {


public static void main(String[] args) throws Exception {


// 从文件中读取的数据或者从表单中读取的数据都是字符串
String id = "110";
String name = "徐立飞";
String salary = "8000";
String hireDate = "1994-8-11";
// 注册一个类型转换器
ConvertUtils.convert(new Converter() {


@Override
public Object convert(Class type, Object value) {// type是当前需要转换的类型,value当前参数的值
SimpleDateFormat sFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sFormat.parse((String) value);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return date;
}


}


, Date.class);//Date.class是当前需要转换的类型
Person p = new Person();
BeanUtils.setProperty(p, "id", id);
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "salary", salary);
BeanUtils.setProperty(p, "hireDate", hireDate);

 System.out.println(p);
}


}



Person类:


package javaee_review.Beanutls封装对象数据到对象;


import java.util.Date;


public class Person {
       private int id;
       private String name;
       private double salary;
       private Date hireDate;
       public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
       public Date getHireDate() {
return hireDate;
}
       
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
       
@Override
public String toString() {
// TODO Auto-generated method stub
return "[id="+id+"  name="+name+"  salary="+salary+"  hireDate="+hireDate+"  ]";
}


}



你可能感兴趣的:(使用内省封装数据到对象中)