JavaEE JavaBean 反射、内省、BeanUtils
2016-09-03 11:21
323 查看
JavaEE JavaBean 反射、内省、BeanUtils
@author ixenosJavaBean是什么
一种规范,表达实体和信息的规范,便于封装重用。1、所有属性为private
2、提供默认构造方法
3、提供getter和setter
4、实现serializable接口
public class Person implements Serializable{ private int age; private String name; public Person(){} public Person(int age, String name){ this.age = age; this.name = name; } public void setAge(int age){ this.age = age; } public void setName(String name){ this.name = name; } public int getAge(){ return this.age; } public String getName(){ return this.name; } }
现有一需求:封装JavaBean数据
由于不知JavaBean具体类型,所以编写一个工厂方法,根据配置文件内容中的一些属性数据,把对象的属性数据封装到对象(JavaBean)中,工厂方法返回对应的对象(JavaBean)。在没学任何工具之前,作为工厂方法,第一时间想到的自然是利用反射创建对象。
反射的思路:解析配置文件,获取Field
1.通过流读取配置文件,获取到完整的类名
2.由类名获得Class对象,此时先newInstance获得一个默认JavaBean
3.通过流读取配置文件,由正则表达式分别获取变量名和变量值
4.根据变量名由Class对象获得Field对象,然后调用set方法设置默认JavaBean的属性数据
import java.io.BufferedReader; import java.io.FileReader; import java.lang.reflect.Constructor; import java.lang.reflect.Field; /** * 反射的思路,解析配置文件,获取Field * * @author ixenos * */ public class Demo1 { public static void main(String[] args) throws Exception { Person p = (Person)getInstance(); System.out.println(p); } //根据配置文件的内容产生对象的对象,并且要把对象的属性值封装到对象中 public static Object getInstance() throws Exception{ BufferedReader bufferedReader = new BufferedReader(new FileReader("obj.txt")); String className = bufferedReader.readLine();//读取配置文件,获取到完整的类名 Class<?> clazz = Class.forName(className); //通过class对象获取到无参构造方法 Constructor<?> constructor = clazz.getConstructor(); //通过构造器对象创建对象 Object o = constructor.newInstance(); //读取属性值 String line = null; while((line = bufferedReader.readLine()) != null){ /* split字符串,根据给定正则表达式的匹配拆分此字符串,返回String[]数组 左边的为datas[0],右边的为datas[1] */ 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]); } } bufferedReader.close(); return null; } }
开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API:内省(Intorspector),专门用于操作java对象的属性。
内省(Introspector)
内省原理:
1.读取配置文件信息2.根据信息利用反射构建Class对象、默认JavaBean和具体的set和get方法的Method对象
3.如果一个类中没有setter和getter方法,那么内省就没用了,因为内省是根据这两个方法来操纵属性数据的
因此内省是一个变态的反射,与上面反射思路不同在于默认读取JavaBean,由Method对象来set
为什么要学内省?
内省是用于操作java对象的属性的,那么以下问题我们必须要清楚。问题一: 什么是Java对象的属性和属性的读写方法?
答: 非静态Field及其setter和getter
问题二: 如何通过内省访问到javaBean的属性 ?
答:内省有两种方式:
1.通过PropertyDescriptor类操作JavaBean的某个属性,获得已知对象某个属性的setter和getter方法
/* 通过属性描述器,获得已知对象某个属性的setter和getter方法,从而来填入属性 */ public void testProperty() throws Exception { Person p = new Person(); //属性描述器 (property即是属性) PropertyDescriptor descriptor = new PropertyDescriptor("id", Person.class); //获取属性对应的get或者set方法来设置或者获取属性 Method m = descriptor.getWriteMethod();//获取属性的set方法 //执行该方法设置属性值 m.invoke(p, 100); Method readMethod = descriptor.getReadMethod();//获取属性的get方法 System.out.println(readMethod.invoke(p)); }
2.通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取所有PropertyDescriptor,
通过这个属性描述器就可以获取每个属性对应的 getter/setter 方法,
/* 通过BeanInfo获得一个类中的所有属性描述器 */ public void getAllProperty() throws IntrospectionException{ //IntroSpector 内省类 BeanInfo beanInfo = Introspector.getBeanInfo(Person.class); //通过BeanInfo获取所有的属性描述器 PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();//获取一个类中的所有属性描述器 for(PropertyDescriptor p : descriptors){ System.out.println(p.getReadMethod());//获取一个类中所有的get方法 } }
内省依旧存在的问题:
sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils。
Apache的BeanUtils
Apache的BeanUtils和Sun的IntroSpector主要解决的问题都是: 把对象的属性数据封装到对象中。而且同样依赖JavaBean的setter和getter方法(Method, not Field)
BeanUtils的好处:
1. BeanUtils设置属性值的时候,如果属性是基本数据类型,BeanUtils会自动转换数据类型。
2. BeanUtils设置属性值的时候,如果属性是引用数据类型,那么这时候必须要注册一个类型转换器。
3. BeanUtils设置属性值的时候底层也是依赖setter和getter方法设置以及获取属性值的。
设置基本数据类型示例:
import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.beanutils.BeanUtils; public class Demo3 { public static void main(String[] args) throws Exception { //从文件中读取到的数据都是字符串的数据,或者是表单提交的数据获取到的时候也是字符串的数据。 String id ="110"; String name="ixenos"; String salary = "1000.0"; Emp e = new Emp(); //对应JavaBean,属性名(字符串),属性(变量) BeanUtils.setProperty(e, "id", id); BeanUtils.setProperty(e, "name",name); BeanUtils.setProperty(e, "salary",salary); System.out.println(e); } }
设置引用类型示例:
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设置属性值,如果设置的属性是其他的引用 类型数据,那么这时候必须要注册一个类型转换器。 */ public class Demo3 { public static void main(String[] args) throws Exception { //从文件中读取到的数据都是字符串的数据,或者是表单提交的数据获取到的时候也是字符串的数据。 String id ="110"; String name="ixenos"; String salary = "1000.0"; String birthday = "2013-12-10";//引用类型使用BeanUtils要注册类型转换器 //注册一个类型转换器 ConvertUtils.register(new Converter() { @Override public Object convert(Class type, Object value) { // type : type to which this value should be converted。 将在register填入Date.class 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); Emp e = new Emp(); BeanUtils.setProperty(e, "id", id); BeanUtils.setProperty(e, "name",name); BeanUtils.setProperty(e, "salary",salary); BeanUtils.setProperty(e, "birthday",birthday); System.out.println(e); } }
相关方法签名:
public static void setProperty(Object bean, String name, Object value)
形参对应JavaBean,属性名,属性(基本数据类型已注册,引用类型要手动注册才可调用此方法)
public static void register(Converter converter, Class clazz)
形参对应Converter,属性类型对象
Converter是个接口,有一些实现类可用,也可自行(用匿名对象)实现
public Object convert(Class type, Object value)
// type : type to which this value should be converted,将在register填入Date.class
即clazz将自动填入type
实现Converter接口需要重写其中的convert方法,主要是要使字符串转换成对应类型的对象
相关文章推荐
- Java的反射(Reflection)、内省(Retrospector)和beanUtils工具
- 基础加强 JAVABean内省 BeanUtils使用
- java反射及javaBean内省机制
- Java_反射_内省JavaBean
- 泛型、JavaBean内省、beanutils工具包
- java基础加强(反射、内省、BeanUtils工具类、类加载器、动态代理)
- Java基础增强3-反射,内省,beanutils,泛型
- Java的反射,内省,beanUtils工具
- BeanUtils和Cglib的Java Bean属性copy功能的性能比较
- JAVA BEAN反射组装数据小工具
- java的反射与内省机制的实现
- Java--introspector(内省)操作bean属性
- 用BeanUtils类自动封装表单数据到javabean
- 反射与内省(一)Java
- java高新技术之使用反射和内省对对象的操作
- JAVA的内省机制(introspector)与反射机制(reflection)
- 理解java的内省与反射
- 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)
- 利用Java反射实现JavaBean对象相同属性复制并初始化目标对象为空的属性的BeanUtils
- Introspector内省和反射的区别. 什么是Bean,对应的jdk概念有哪些,