java反射内省机制,Introspector

来源:互联网 发布:删除表数据 编辑:程序博客网 时间:2024/06/06 06:33

1.为什么要学内省?

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

2.反射技术

以后我们能开发框架的时候,经常需要把一些数据封装到对象中去
需求:编写一个工厂方法根据配置文件的内容,工厂方法返回对应的对象,并且对象要有对应的属性值
Person.java

package day01.introspector;public class Person {    int id;    String name;    public Person(int id, String name) {        super();        this.id = id;        this.name = name;    }    public Person() {        super();    }    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;    }    @Override    public String toString() {        return "Person [id=" + id + ", name=" + name + "]";    }}//obj.txtday01.introspector.Personid=110name=张兵杰//One.javapackage day01.introspector;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;public class One {        Person p = (Person)getInstance();        System.out.println(p);    }    //根据配置文件生产对应的对象并且要把对象的属性值封装到对象中    public static Object getInstance() throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, NoSuchFieldException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{        BufferedReader bufferedReader = new BufferedReader(new FileReader("obj.txt"));        String className = bufferedReader.readLine();//读取配置文件获取到完整的类名        Class clazz = Class.forName(className);        //通过clazz对象获取到无参的构造方法        Constructor constructor = clazz.getConstructor(null);        //创建对象        Object o = constructor.newInstance(null);        //读取属性值        String line = null;        while((line = bufferedReader.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;    }}

内省======一个变态的反射
内省主要解决的问题:把对象的属性数据封装到对象中去

//Two.javapackage day01.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;public class Two {    public static void main(String args[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException{        testProperty1();    }    public static void testProperty1() throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{        Person p = new Person();        //属性描述器    属性名+属性类        PropertyDescriptor descriptor = new PropertyDescriptor("id",Person.class);        //获取属性对应的get或者是set方法设置或者获取属性        Method m = descriptor.getWriteMethod();//获取属性set方法        //执行该方法设置属性值        m.invoke(p, 110);        //Method类代表一个方法,invoke(调用)就是调用Method类代表的方法        Method readMethod = descriptor.getReadMethod();//获取属性get方法        System.out.println(p);        System.out.println(readMethod.invoke(p, null));    }    public void getAllProperty() throws IntrospectionException{        //Introspector 内省类        BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);        //通过BeanInfo获取所有的属性描述器        PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();//获取一个类中的所有属性描述器        for (PropertyDescriptor propertyDescriptor : descriptors) {            System.out.println(propertyDescriptor.getReadMethod());//get方法        }    }}

BeanUtils:
BeanUtils主要解决的问题:把对象的属性数据封装到对象中

BeanUtils的好处
1.BeanUtils设置属性值时候,如果属性是基本数据类型,BeanUtils会自动帮我们转化数据类型
2.BeanUtils设置属性值时候,底层也是依赖于get,set方法设置以及获取属性值的
3.BeanUtils设置属性值,如果设置的属性是其他的引用 类型数据,比如Date,那么这时候必须要注册一个类型转换器

//Three.javapackage day01.introspector;import java.lang.reflect.InvocationTargetException;import java.util.Date;import java.text.SimpleDateFormat;import javax.xml.crypto.Data;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.beanutils.Converter;public class Three {    public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {        //从文件中读取到的数据都是字符串的数据,或者是表单提交的数据获取到的时候也是字符串的数据        String id = "110";        String name = "张兵杰";        Person p = new Person();        BeanUtils.setProperty(p, "id", id);        BeanUtils.setProperty(p, "name", name);        System.out.println(p);        //日期不会自动转换,需要自己注册一个类型转换器        String birthday = "2017-7-25";        ConvertUtils.register(new Converter() {            @Override            public Object convert(Class type, Object value) {//type目前所遇到的数据类型。value目前参数的值                Date date = null;                try{                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");                    date = dateFormat.parse((String)value);                }catch(Exception e){                    e.printStackTrace();                }                return date;            }        },Date.class);    }}