JavaEE JavaBean 反射、内省、BeanUtils
JavaEE JavaBean 反射、内省、BeanUtils
@author ixenos
JavaBean是什么
一种规范,表达实体和信息的规范,便于封装重用。
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方法,主要是要使字符串转换成对应类型的对象
JavaEE JavaBean 反射、内省、BeanUtils的更多相关文章
- Java反射之对JavaBean的内省操作
上一篇我们说了Java反射之数组的反射应用 这篇我们来模拟实现那些javabean的框架(BeanUtils)的基本操作. [一] 什么是JavaBean JavaBean 是一种JAVA语言写成的可 ...
- JavaBean和内省
JavaBean和内省 JavaBean是一个遵循特定的写法的java类 1. 必须有一个无参的构造方法 2.属性私有化 3.私有你给的属性必须通过public类型的方法暴露给 ...
- javabean以及内省技术详解(转)
一.关于javabean javabean是固定写法的java类 书写格式为: 1)必须有无参构造函数 2)属性必须私有, 我们称为字段 3)提供标准的getter和setter 例: name 字段 ...
- JAVAWEB开发之Session的追踪创建和销毁、JSP具体解释(指令,标签,内置对象,动作即转发和包括)、JavaBean及内省技术以及EL表达式获取内容的使用
Session的追踪技术 已知Session是利用cookie机制的server端技术.当client第一次訪问资源时 假设调用request.getSession() 就会在server端创建一个由 ...
- (反射+内省机制的运用)处理jdbc的结果集
1.原理:反射+内省 2.反射:动态创建对象 3.内省:动态处理对象的属性值 4.结果集处理: (1)把结果集中的一行数据,封装成一个对象,专门针对结果集中只有一行数据的情况. (2)处理结果集--多 ...
- JAVA中反射机制五(JavaBean的内省与BeanUtils库)
内省(Introspector) 是Java 语言对JavaBean类属性.事件的一种缺省处理方法. JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法 ...
- javabean的内省技术和BeanUtils的使用
一.关于javabean javabean是固定写法的java类 书写格式为: 1)必须有无参构造函数 2)属性必须私有, 我们称为字段 3)提供标准的getter和setter 例: name 字段 ...
- Javaweb学习笔记——(十二)——————JSP指令:page指令、include指令、taglib指令,JavaBean,内省,EL表达式
JSP指令JSP指令分类 JSP有三大指令: *page指令 *include指令 *taglib指令 在JSP中没有任何指令是必须的. 但基本上每个JSP都是使用page指令============ ...
- day13(反射,BeanUtils包)
反射, 获取字节码文件的方式: 方式一: 对象.getClass(); 方式二: 类名.Class; 方式三: Class.forName(String Class); 通过字节码文件获取对象 定 ...
随机推荐
- 怎么删除hao.qquu8.com绑定
运行 输入 regedit 编辑 - 查找 hao.qquu8.com 然后修改成 你想绑定的 主页 就好
- Android studio使用smack连接xmpp服务器收发消息
我使用的是ejabberd16.09的Linux版本,安装教程网上有很多,我在这里只介绍一下Android端连接.登录和收发消息的方法.文章最后附上了我写的一个demo,欢迎大家参考. ejabber ...
- 关于64位win7环境下VS连接oracle数据库的问题
本机环境:64位win7,安装了64位的oracle桌面类 服务器环境:64位windows server 2008,64位oracle服务器端 问题:本机用sql developer连数据库没有问题 ...
- Python中is和==的区别的
在python中,is检查两个对象是否是同一个对象,而==检查他们是否相等. str1 = 'yangshl' str2 = 'yang' + 'shl' print('str1 == str2:', ...
- AFURLRequestSerialization
NSString * AFPercentEscapedStringFromString(NSString *string) //去除非法字符并且对特殊字符进行编码. //对字符串进行百分比编码 ...
- Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版
软件名称:Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 4.40MB 图片 ...
- 敏捷开发(八)- Scrum Sprint计划会议1
本文主要是为了检测你对SCRUM Sprint 计划会议的了解和使用程度, 通过本文你可以检测一下 1.你们的SCRUM Sprint 计划会议的过程和步骤 2.会议的输出结果 S ...
- HDU 5869 Different GCD Subarray Query
离线操作,树状数组,$RMQ$. 这个题的本质和$HDU$ $3333$是一样的,$HDU$ $3333$要求计算区间内不同的数字有几个. 这题稍微变了一下,相当于原来扫描到$i$的之后是更新$a[i ...
- google 技巧
inurl: 用于搜索网页上包含的URL. 这个语法对寻找网页上的搜索,帮助之类的很有用. intext: 只搜索网页部分中包含的文字(也就是忽略了标题,URL等的文字). site: 可以限制你搜索 ...
- dplyr 数据操作 常用函数(5)
继续来了解dplyr中的其他有用函数 1.sample() 目的是可以从一个数据框中,随机抽取一些行,然后组成新的数据框. sample_n(tbl, size, replace = FALSE, w ...