JavaEE JavaBean 反射、内省、BeanUtils

@author ixenos

JavaBean是什么


一种规范,表达实体和信息的规范,便于封装重用。

1、所有属性为private
2、提供默认构造方法
3、提供getter和setter
4、实现serializable接口

  1. public class Person implements Serializable{
  2. private int age;
  3. private String name;
  4.  
  5. public Person(){}
  6.  
  7. public Person(int age, String name){
  8. this.age = age;
  9. this.name = name;
  10. }
  11.  
  12. public void setAge(int age){
  13. this.age = age;
  14. }
  15. public void setName(String name){
  16. this.name = name;
  17. }
  18. public int getAge(){
  19. return this.age;
  20. }
  21. public String getName(){
  22. return this.name;
  23. }
  24. }

现有一需求:封装JavaBean数据


  由于不知JavaBean具体类型,所以编写一个工厂方法,根据配置文件内容中的一些属性数据,把对象的属性数据封装到对象(JavaBean)中,工厂方法返回对应的对象(JavaBean)。 

  在没学任何工具之前,作为工厂方法,第一时间想到的自然是利用反射创建对象。

反射的思路:解析配置文件,获取Field

  1.通过流读取配置文件,获取到完整的类名

  2.由类名获得Class对象,此时先newInstance获得一个默认JavaBean

  3.通过流读取配置文件,由正则表达式分别获取变量名和变量值

  4.根据变量名由Class对象获得Field对象,然后调用set方法设置默认JavaBean的属性数据

  1. import java.io.BufferedReader;
  2. import java.io.FileReader;
  3. import java.lang.reflect.Constructor;
  4. import java.lang.reflect.Field;
  5.  
  6. /**
  7. * 反射的思路,解析配置文件,获取Field
  8. *
  9. * @author ixenos
  10. *
  11. */
  12. public class Demo1 {
  13.  
  14. public static void main(String[] args) throws Exception {
  15. Person p = (Person)getInstance();
  16. System.out.println(p);
  17. }
  18.  
  19. //根据配置文件的内容产生对象的对象,并且要把对象的属性值封装到对象中
  20. public static Object getInstance() throws Exception{
  21. BufferedReader bufferedReader = new BufferedReader(new FileReader("obj.txt"));
  22. String className = bufferedReader.readLine();//读取配置文件,获取到完整的类名
  23. Class<?> clazz = Class.forName(className);
  24. //通过class对象获取到无参构造方法
  25. Constructor<?> constructor = clazz.getConstructor();
  26. //通过构造器对象创建对象
  27. Object o = constructor.newInstance();
  28. //读取属性值
  29. String line = null;
  30. while((line = bufferedReader.readLine()) != null){
  31. /*
  32. split字符串,根据给定正则表达式的匹配拆分此字符串,返回String[]数组
  33. 左边的为datas[0],右边的为datas[1]
  34.  
  35. */
  36. String[] datas = line.split("=");
  37. //通过属性名获取到对应的Field对象
  38. Field field = clazz.getDeclaredField(datas[0]);
  39. if(field.getType() == int.class){
  40. field.set(o, Integer.parseInt(datas[1]));
  41. }else{
  42. field.set(o, datas[1]);
  43. }
  44. }
  45. bufferedReader.close();
  46.  
  47. return null;
  48. }
  49. }

  开发框架时,经常需要使用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方法

  1. /*
  2. 通过属性描述器,获得已知对象某个属性的setter和getter方法,从而来填入属性
  3. */
  4. public void testProperty() throws Exception {
  5. Person p = new Person();
  6. //属性描述器 (property即是属性)
  7. PropertyDescriptor descriptor = new PropertyDescriptor("id", Person.class);
  8. //获取属性对应的get或者set方法来设置或者获取属性
  9. Method m = descriptor.getWriteMethod();//获取属性的set方法
  10. //执行该方法设置属性值
  11. m.invoke(p, 100);
  12. Method readMethod = descriptor.getReadMethod();//获取属性的get方法
  13. System.out.println(readMethod.invoke(p));
  14.  
  15. }

    

     2.通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取所有PropertyDescriptor,

      通过这个属性描述器就可以获取每个属性对应的 getter/setter 方法,

  1. /*
  2. 通过BeanInfo获得一个类中的所有属性描述器
  3. */
  4. public void getAllProperty() throws IntrospectionException{
  5. //IntroSpector 内省类
  6. BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
  7. //通过BeanInfo获取所有的属性描述器
  8. PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();//获取一个类中的所有属性描述器
  9. for(PropertyDescriptor p : descriptors){
  10. System.out.println(p.getReadMethod());//获取一个类中所有的get方法
  11. }
  12.  
  13. }

  内省依旧存在的问题

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方法设置以及获取属性值的。

  设置基本数据类型示例:

  1. import java.text.SimpleDateFormat;
  2. import java.util.Date;
  3.  
  4. import org.apache.commons.beanutils.BeanUtils;
  5.  
  6. public class Demo3 {
  7.  
  8. public static void main(String[] args) throws Exception {
  9. //从文件中读取到的数据都是字符串的数据,或者是表单提交的数据获取到的时候也是字符串的数据。
  10. String id ="110";
  11. String name="ixenos";
  12. String salary = "1000.0";
  13.  
  14. Emp e = new Emp();
  15. //对应JavaBean,属性名(字符串),属性(变量)
  16. BeanUtils.setProperty(e, "id", id);
  17. BeanUtils.setProperty(e, "name",name);
  18. BeanUtils.setProperty(e, "salary",salary);
  19.  
  20. System.out.println(e);
  21. }
  22. }

  设置引用类型示例:

  1. import java.text.SimpleDateFormat;
  2. import java.util.Date;
  3.  
  4. import org.apache.commons.beanutils.BeanUtils;
  5. import org.apache.commons.beanutils.ConvertUtils;
  6. import org.apache.commons.beanutils.Converter;
  7.  
  8. /*
  9.  
  10. BeanUtils设置属性值,如果设置的属性是其他的引用 类型数据,那么这时候必须要注册一个类型转换器。
  11.  
  12. */
  13. public class Demo3 {
  14.  
  15. public static void main(String[] args) throws Exception {
  16. //从文件中读取到的数据都是字符串的数据,或者是表单提交的数据获取到的时候也是字符串的数据。
  17. String id ="110";
  18. String name="ixenos";
  19. String salary = "1000.0";
  20. String birthday = "2013-12-10";//引用类型使用BeanUtils要注册类型转换器
  21.  
  22. //注册一个类型转换器
  23. ConvertUtils.register(new Converter() {
  24.  
  25. @Override
  26. public Object convert(Class type, Object value) { // type : type to which this value should be converted。 将在register填入Date.class
  27. Date date = null;
  28. try{
  29. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  30. date = dateFormat.parse((String)value);
  31. }catch(Exception e){
  32. e.printStackTrace();
  33. }
  34. return date;
  35. }
  36.  
  37. }, Date.class);
  38.  
  39. Emp e = new Emp();
  40. BeanUtils.setProperty(e, "id", id);
  41. BeanUtils.setProperty(e, "name",name);
  42. BeanUtils.setProperty(e, "salary",salary);
  43. BeanUtils.setProperty(e, "birthday",birthday);
  44.  
  45. System.out.println(e);
  46. }
  47. }

相关方法签名

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方法,主要是要使字符串转换成对应类型的对象

JavaEE JavaBean 反射、内省、BeanUtils的更多相关文章

  1. Java反射之对JavaBean的内省操作

    上一篇我们说了Java反射之数组的反射应用 这篇我们来模拟实现那些javabean的框架(BeanUtils)的基本操作. [一] 什么是JavaBean JavaBean 是一种JAVA语言写成的可 ...

  2. JavaBean和内省

    JavaBean和内省 JavaBean是一个遵循特定的写法的java类     1. 必须有一个无参的构造方法     2.属性私有化     3.私有你给的属性必须通过public类型的方法暴露给 ...

  3. javabean以及内省技术详解(转)

    一.关于javabean javabean是固定写法的java类 书写格式为: 1)必须有无参构造函数 2)属性必须私有, 我们称为字段 3)提供标准的getter和setter 例: name 字段 ...

  4. JAVAWEB开发之Session的追踪创建和销毁、JSP具体解释(指令,标签,内置对象,动作即转发和包括)、JavaBean及内省技术以及EL表达式获取内容的使用

    Session的追踪技术 已知Session是利用cookie机制的server端技术.当client第一次訪问资源时 假设调用request.getSession() 就会在server端创建一个由 ...

  5. (反射+内省机制的运用)处理jdbc的结果集

    1.原理:反射+内省 2.反射:动态创建对象 3.内省:动态处理对象的属性值 4.结果集处理: (1)把结果集中的一行数据,封装成一个对象,专门针对结果集中只有一行数据的情况. (2)处理结果集--多 ...

  6. JAVA中反射机制五(JavaBean的内省与BeanUtils库)

    内省(Introspector) 是Java 语言对JavaBean类属性.事件的一种缺省处理方法. JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法 ...

  7. javabean的内省技术和BeanUtils的使用

    一.关于javabean javabean是固定写法的java类 书写格式为: 1)必须有无参构造函数 2)属性必须私有, 我们称为字段 3)提供标准的getter和setter 例: name 字段 ...

  8. Javaweb学习笔记——(十二)——————JSP指令:page指令、include指令、taglib指令,JavaBean,内省,EL表达式

    JSP指令JSP指令分类 JSP有三大指令: *page指令 *include指令 *taglib指令 在JSP中没有任何指令是必须的. 但基本上每个JSP都是使用page指令============ ...

  9. day13(反射,BeanUtils包)

    反射, 获取字节码文件的方式: 方式一: 对象.getClass(); 方式二: 类名.Class; 方式三:   Class.forName(String Class); 通过字节码文件获取对象 定 ...

随机推荐

  1. [UWP小白日记-4]记账项目-2

    手机端: 待续…… 哈哈这个代码真是好长时间啊,没办法萌新你们都懂的,UI是改了又改,知识也在慢慢积累, 所以这效率就低下了点 UI是改了又改,代码是不断了改,所以搞到现在都没开发完成

  2. JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解

    Jmap是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本.打印出某个java进程(使用pid)内存内的,所有'对象'的情况(如:产生那些对象,及其数量). 使用方法 ...

  3. Jenkins配置和使用

    之前整理了Jenkins的下载和安装过程,有需要的可以参考我的博客,地址:   http://www.cnblogs.com/luchangyou/p/5981884.html 接下来整理一下Jenk ...

  4. 计算机网络课程优秀备考PPT之第七章应用层(七)

    为了记录自己从2016.9~2017.1的<计算机网络>助教生涯,也为了及时梳理和整写笔记! 前期博客是, 计算机网络课程优秀备考PPT之第一章概述(一) 计算机网络课程优秀备考PPT之第 ...

  5. JavaScriptSerializer返回一条Json,页面获取值问题,数据绑定

    一,后台处理数据方法 JavaScriptSerializer serializer = new JavaScriptSerializer(); string js = serializer.Seri ...

  6. 安装配置Postgresql

    //关闭selinuxgetenforcesetenfroce 0vi /etc/selinux/configSELINUX=disabledSELINUXTYPE=targeted//关闭防火墙#c ...

  7. Java 序列化 序列化与单例模式 [ 转载 ]

    Java 序列化 序列化与单例模式 [ 转载 ] @author Hollis 本文将通过实例+阅读Java源码的方式介绍序列化是如何破坏单例模式的,以及如何避免序列化对单例的破坏. 单例模式,是设计 ...

  8. 加速Android Studio的Gradle构建速度

    在利用Android Studio做项目时,发现随着项目内资源的逐渐增多(或者项目创建时间太过久远,而又未经常打开),Android Studio的build速度也越来越慢.(P.S.在做我的CSGO ...

  9. F4IF_FIELD_VALUE_REQUEST 和 F4IF_INT_TABLE_VALUE_REQUEST的不同

    F4IF_FIELD_VALUE_REQUEST 和 F4IF_INT_TABLE_VALUE_REQUEST的不同 F4IF_FIELD_VALUE_REQUEST主要功能是将表里的字段对应的sea ...

  10. drupal 连表查询+分页

    $query = db_select('Table','t'); $query->join('Table_A','a','on条件); $query->join('Table_B','b' ...