java内省技术_JAVA高新技术《内省》

一、概述:

1、IntroSpector:即内省,是对内部进行检查,了解更多的底层细节。

2、内省的作用:主要针对JavaBean进行操作。

二、JavaBean(存在于java.bean包中)

1、简述:

1)JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法名都符合某种特殊的命名规则。

2)它是一种特殊的Java类,其中的方法名称等,都符合特殊的规则。只要一个类中含有get和set打头的方法,就可以将其当做JavaBean使用。

3)字段和属性:

字段就是我们定义的一些成员变量,如private String name;等

而属性是具有某些功能,Bean属性,是含有get或set方法的那些属性的字段,即这个变量的get属性,set属性等。

2、作用:

如果要在两个模板之间传递多个信息,可将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value

Object,简称VO),这些信息在类中用私有字段来储存,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。

3、命名方式:

JavaBean的属性是根据其中的setter和getter方法来确定的,而不是依据其中的变量,如方法名为setId,则中文意思是设置Id,getId也是如此;去掉前缀,剩余部分就是属性名称,如果剩余部分的第二个字母小写,则把剩余部分改为小写。如:getAge/setAge-->age;gettime-->time;setTime-->time;getCPU-->CPU。

4、总之、一个类被当做JavaBean使用时,JavaBaan的属性是根据方法名推断出来的,它根本看不到Java类内部的成员变量。

5、JavaBean的好处:

一个符合JavaBean特点的类当做普通类一样可以使用,但是把它当做JavaBean类用肯定有好处的:

1)在JavaEE开发中,经常要使用JavaBean。很多环境就要求按JavaBean的方式进行操作,别人都这么用,那么就必须要求这么做。

2)JDK中提供了对JavaBean进行操作的API,这套API称为内省,若要自己通过getX的方式来访问私有x,可用内省这套API,操作JavaBean要比使用普通的方式更方便。

示例:

packagecn.itcast.text1;

importjava.beans.BeanInfo;

importjava.beans.IntrospectionException;

importjava.beans.Introspector;

importjava.beans.PropertyDescriptor;

importjava.lang.reflect.InvocationTargetException;

importjava.lang.reflect.Method;

publicclassIntroSpectorTest {

//上面的get或set代码分别通过选中要重构的代码,通过右击选重构获得get和set方法:

publicstaticvoidmain(String[] args)throwsException {

// TODO Auto-generated method stub

ReflectPoint pt1 =newReflectPoint(3,5);

String propertyName ="x";

//一般方式:"x"-->"X"-->"getX"-->MethodGetX-->

//内省方式:

//通过get和set方法获取属性值

Object retVal = getProperty(pt1, propertyName);

System.out.println(retVal);

Object value =7;

setProperty(pt1, propertyName, value);

System.out.println(pt1.getX());

}

//设置属性值的方法 //此处的类型为Object,通用,下同

privatestaticvoidsetProperty(Object rf, String propertyName,

Object value)throwsIntrospectionException,

IllegalAccessException, InvocationTargetException {

//创建属性描述符对象,将属性名称和加载文件等信息写入其中

PropertyDescriptor pd =

newPropertyDescriptor(propertyName,rf.getClass());

//通过反射的方法类Method,获取属性所对应的set方法

Method methodSetX = pd.getWriteMethod();

methodSetX.invoke(rf, value);

}

//获取属性值的方法

privatestaticObject getProperty(Object rf, String propertyName)

throwsIntrospectionException, IllegalAccessException,

InvocationTargetException {

//创建属性描述符对象,获取属性所对应的名称和加载文件等信息

PropertyDescriptor pd =

newPropertyDescriptor(propertyName,rf.getClass());

//通过反射的方法类Method,获取属性所对应的get方法

Method methodGetX = pd.getReadMethod();

Object retVal = methodGetX.invoke(rf);

returnretVal;

}

}

三、对JavaBean的复杂内省操作:

1、在IntroSpector类中有getBeanInfo(Class cls)的方法。

2、获取Class对象的Bean信息,返回的是BeanInfo类型。

3、BeanInfo类中有getPropertyDescriptors()的方法,可获取所有的BeanInfo的属性信息,返回一个PropertyDescriptor[]。

4、在通过遍历的形式,找出与自己想要的那个属性信息。

如:改写get方法:

BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());

PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();

Object value =null;

for(PropertyDescriptor pd : pds){

if(pd.getName().equals(propertyName)){

Method methodGetX = pd.getReadMethod();

value = methodGetX.invoke(pt1);

break;

}

}

这种方式要比上面的方法复杂些。

四、BeanUtils工具包:

1、BeanUtils等工具包都是由阿帕奇提供的,为了便于开发。

2、BeanUtils可以将8种基本数据类型进行自动的转换,因此对于非基本数据类型,就需要注册转换器Converter,这就需要ConverUtils包,

2、好处:

1)提供的set或get方法中,传入的是字符串,返回的还是字符串,因为在浏览器中,用户输入到文本框的都是以字符串的形式发送至服务器上的,所以操作的都是字符串。也就是说这个工具包的内部有自动将整数转换为字符串的操作。

2)支持属性的级联操作,即支持属性链。如可以设置:人的脑袋上的眼镜的眼珠的颜色。这种级联属性的属性连如果自己用反射,那就很困难了,通过这个工具包就可以轻松调用。

3、可以和Map集合进行相互转换:可将属性信息通过键值对的形式作为Map集合存储(通过staticjava.util.Map

describe(java.lang.Object

bean)的方法),也可以将Map集合转换为JavaBean中的属性信息(通过static

voidpopulate(java.lang.Object bean, java.util.Map

properties)的方法)。

4、示例:

1)设置和获取属性值:

importjava.lang.reflect.InvocationTargetException;

importjava.text.ParseException;

importjava.text.SimpleDateFormat;

importjava.util.Date;

importjava.util.Map;

importjava.util.TreeMap;

importorg.apache.commons.beanutils.BeanUtils;

importorg.apache.commons.beanutils.ConversionException;

importorg.apache.commons.beanutils.ConvertUtils;

importorg.apache.commons.beanutils.Converter;

importorg.apache.commons.beanutils.PropertyUtils;

importorg.apache.commons.beanutils.locale.converters.DateLocaleConverter;

importorg.junit.Test;

publicclassBeanUtilDemo {

@Test

publicvoidtest1()throwsException{

//创建对象,设置属性值

Person p =newPerson();

BeanUtils.setProperty(p,"name","zzz");

String name = BeanUtils.getProperty(p,"name");

System.out.println(name);

}

@Test

publicvoidtest2()throwsException{

//创建对象,传入属性值

Person p =newPerson();

String name ="wangwu";

String age ="23";

String hight ="173.5";

//设置属性值

BeanUtils.setProperty(p,"name", name);

BeanUtils.setProperty(p,"age", age);

BeanUtils.setProperty(p,"hight", hight);

//获取属性值

System.out.println(BeanUtils.getProperty(p,"name"));

System.out.println(BeanUtils.getProperty(p,"age"));

System.out.println(BeanUtils.getProperty(p,"hight"));

}

2)未注册的属性值的获取和设置

//获取未注册的属性,即非八种基本数据类型的引用类型

//private Date birthday

@Test

publicvoidtest3()throwsException{

Person p =newPerson();

String name ="wangwu";

String age ="23";

String hight ="173.5";

String birthday ="1990-09-09";

ConvertUtils.register(newConverter() {

//注册器Converter接口中方法的重写

@Override

publicObject convert(Class type, Object value) {

if(value ==null)

returnnull;

if(!(valueinstanceofString))

thrownewConversionException("只支持String类型的转换");

String str = (String) value;

if(value.equals(""))

returnnull;

SimpleDateFormat sdf =newSimpleDateFormat("yyyy-MM-dd");

try{

returnsdf.parse(str);

}catch(ParseException e){

thrownewRuntimeException(e);//异常链不能掉,这里必须写上e

}

}},

Date.class);

//测试

BeanUtils.setProperty(p,"name", name);

BeanUtils.setProperty(p,"age", age);

BeanUtils.setProperty(p,"hight", hight);

BeanUtils.setProperty(p,"birthday", birthday);

System.out.println(BeanUtils.getProperty(p,"name"));

System.out.println(BeanUtils.getProperty(p,"age"));

System.out.println(BeanUtils.getProperty(p,"hight"));

System.out.println(BeanUtils.getProperty(p,"birthday"));

}

//使用已经写好的注册器DateLocaleConverter

@Test

publicvoidtest4()throwsException{

Person p =newPerson();

String name ="wangwu";

String age ="23";

String hight ="173.5";

String birthday ="1990-09-09";

//将日期注册到BeanUtils上

ConvertUtils.register(newDateLocaleConverter(), Date.class);

//提供的注册器不健壮,因为传入空字符串,就会报错

//所以,当没有提供注册器或需要加强注册器的时候,可以自己写

//测试

BeanUtils.setProperty(p,"name", name);

BeanUtils.setProperty(p,"age", age);

BeanUtils.setProperty(p,"hight", hight);

BeanUtils.setProperty(p,"birthday", birthday);

System.out.println(BeanUtils.getProperty(p,"name"));

System.out.println(BeanUtils.getProperty(p,"age"));

System.out.println(BeanUtils.getProperty(p,"hight"));

System.out.println(BeanUtils.getProperty(p,"birthday"));

Date date = p.getBirthday();

System.out.println(date.toLocaleString());

}

3)Map集合在BeanUtils中的应用:

//Map集合在BeanUtils中的应用

@Test

publicvoidtest5()throwsException {

//将数据存入集合

Map map =newTreeMap();

map.put("name","zhangsan");

map.put("age","20");

map.put("hight","172.5");

map.put("birthday","1999-10-02");

//注册器

ConvertUtils.register(newDateLocaleConverter(), Date.class);

//获取属性

Person p =newPerson();

BeanUtils.populate(p, map);

System.out.println(BeanUtils.getProperty(p,"name"));

System.out.println(BeanUtils.getProperty(p,"age"));

System.out.println(BeanUtils.getProperty(p,"hight"));

System.out.println(BeanUtils.getProperty(p,"birthday"));

}

//属性链

@Test

publicvoidtest6()throwsException {

Person p =newPerson();

BeanUtils.setProperty(p,"birthday.time","111212");

System.out.println(BeanUtils.getProperty(p,"birthday.time"));

}

5、补充:

1)BeanUtils是以字符串的形式进行操作的

2)PropertyUtils是以传入值本身的类型进行操作的。

//PropertyUtils可直接解析为指定类型,而BeanUtils只能指定字符串的类型

@Test

publicvoidtest7()throwsException {

Person p =newPerson();

System.out.println("-----BeanUtiles-------");

BeanUtils.setProperty(p,"age","22");//字符串形式

System.out.println(BeanUtils.getProperty(p,"age"));

System.out.println(BeanUtils.getProperty(p,"age").getClass().getName());

System.out.println("-----PropertyUtiles-------");

PropertyUtils.setProperty(p,"age",22);//Integer形式

System.out.println(PropertyUtils.getProperty(p,"age"));

System.out.println(PropertyUtils.getProperty(p,"age").getClass().getName());

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值