`

struts源代码阅读(Commons-Beanutils包)

阅读更多
转自:mariah_fan@hotmail.com

Commons-Beanutils 这个是jakarta commons项目中的一个子项目。这个项目开发的目的是帮助开发者动态的获取/设值Java Bean的属性,同时解决每次都要写getXXX和setXXX的麻烦。

Commons-Beanutils(一)
一、XXXConvert
这些类都实现Converter接口,提供把value值转化成为相应XXX类的实现。现在只针对四种类型:数字,时间,Boolean和String。在 Converter 接口中只有一个方法convert(Class type, Object value),把value对象转换为type所要求的类。XXXConvert类中这个方法的思路是:
1、如果value==null,并且自己内部有缺省的值那么就返回这个缺省的值。如果没有缺省值,就抛出ConversionException异常。
2、如果value instanceOf XXX类,那么就直接返回value。
3、如果上面的都不行,那么调用new XXX(value.toString())或者XXX.valueOf(value.toString())方法来返回。转化失败时,抛出ConversionException异常。

二、特殊的实现
1、对于ClassConverter类,当进入第三种情形的时候,实际执行的是

ClassLoader classLoader =Thread.currentThread().getContextClassLoader();
   if (classLoader == null) {
       classLoader = ClassConverter.class.getClassLoader();
   }
   return (classLoader.loadClass(value.toString()));



2、对于BooleanConverter类,当进入第三种情形的时候,实际执行的是,根据value.toString()的值:yes,y,true, on, 1 返回true;no,n,false,off,0 返回false。如果这些情形都不符合,并且有缺省值的时候则返回缺省值。否则抛出ConversionException;

三、XXXArrayConverter
这些类继承自AbstractArrayConverter类。 AbstractArrayConverter 实际只实现了一个List parseElements(String svalue)方法。这个方法接受的是{value1, value2,...}格式的字符串,逐个解析出来后,放入一个ArrayList中。它通过StreamTokenizer解析字符串:StreamTokenizer是用来分离input stream中读取的字符串,并且可以根据标记区分不同的内容,比如数字,字符或者注释。XXXArrayConverter由于要转换的是一个数组,所以convert(....)方法的实现过程有所不同。
1、如果value==null,并且自己内部有缺省的值那么就返回这个缺省的值。如果没有缺省值,就抛出ConversionException异常。
2、如果model.getClass() == value.getClass(),那么就直接返回value。
3、如果上面的都不行,那么就通过parseElements(value.toString())生成一个数组,再对数组的元素逐个调用new XXX(list.get(i))或者XXX.valueOf(list.get(i))方法,转换成为数组对元素要求的类型。转化失败时,抛出 ConversionException异常。





Commons-Beanutils(二)

一、LocaleConverter 与 BaseLocaleConverter
LocaleConverter继承自 Converter接口,定义了一个新方法convert(Class type, Object value, String pattern)。
抽象类BaseLocaleConverter实现了LocaleConverter接口。它的locPattern属性用来表示这个对象的pattern 是否是本地化的格式。patttern 是指把何种格式的时间或者数字值转换成标准值。convert(...)的执行过程是:
1、如果value==null,并且自己内部有缺省的值那么就返回这个缺省的值。如果没有缺省值,就抛出ConversionException异常。
2、根据参数pattern值是否为null,调用parse(Object value, String pattern)方法:如果这个参数不为null那么就使用这个参数的值,否则使用对象预存的pattern值。如果这
样做引起了异常,会首先判断是否能够返回缺省的值,不能则抛出ConversionException异常。
3、parse(Object value, String pattern)方法的实现被抛至继承了它的类具体实现。这个方法虽然把value值表述为Object类型,但是最后都是通过强制转换,转换成为String类型。也就是说它实际上需要的
是String类型的value。

二、 XXXLocaleConverter
把pattern格式的value转换成标准格式的相应的XXX类。这些类可以分为两大类:一类为时间,一类为数值。
1、时间类最后都会通过SimpleDateFormat类对值进行转换,程序如下:
 if(pattern == null) {      
       pattern = locPattern ? new SimpleDateFormat().toLocalizedPattern() : 
                 new SimpleDateFormat().toPattern();
   }
   SimpleDateFormat format = new SimpleDateFormat(pattern, locale);
   if (locPattern) {
       formatter.applyLocalizedPattern(pattern);
   }else {
       formatter.applyPattern(pattern);
   }
   return formatter.parse((String) value);



2、数值类最后都会通过DecimalFormat类对值进行转换,程序如下:
DecimalFormat formatter = (DecimalFormat) DecimalFormat.getInstance(locale);
   if (pattern != null) {
       if (locPattern) {
           formatter.applyLocalizedPattern(pattern);
       } else {
           formatter.applyPattern(pattern);
       }
   } 
   return formatter.parse((String) value);


这个转化过程要注意精度的问题。由于Number类是所有的数值类的父类,所以转换完成后要检查最后的结果是否是当前要求的精度:如果大于所要求的精度,则抛出ConversionException异常。





Commons-Beanutils(三)

Dyna开头的类,是专门为DynaFormBean而设计的。

一、DynaBean,DynaClass 与 DynaProperty
DynaBean 并不是Java中所定义的Bean,而是一种“假”的Bean。因为它并不是通过getXXX和setXXX方法,对XXX属性进行取值和设值的。它通过一个实现了DynaClass接口的类,帮助管理其所有

的属性的类别,而自己则管理对XXX属性值的设定和获取。在设值的时候会通过与name对应的 DynaProperty对象,检查赋值的类别是否正确。
DynaProperty类描述的是DynaBean中所包含的属性的类型。 DynaProperty类有三个属性:属性的名称:name,属性的名称;type,属性的类别;contentType,如果 DynaProperty描述的是个容

器对象(List或者Map),那么这个contentType就代表这个容器内元素的类别。这个类值得关注的地方是writeObject和readObject方法的实现。它会首先判断自己的type是否是一个

primitive的类,如果是,则先写入true标志,再写入对应的primitive类的编号;否则写入false标志,再写入type。因为在调用readObject方法时,如果得出的是 primitive类型,则type的值

为XXX.TYPE而不是XXX.class。
DynaClass 是一个接口,用来管理DynaBean中所有的DynaProperty属性。

二、BasiceDyanBean 与 BasicDynaClass
BasiceDyanBean 实现自DynaBean接口。它包含一个实现了DynaClass接口的类的对象,和一个用来存放值的HashMap。这个HashMap的key与DynaClass中HashMap的key是一一对应的。
BasicDynaClass 实现了DynaClass接口,以DynaProperty的name为key保存所有这些DynaProperty对象。它通过newInstance 方法动态生成实现了DynaBean接口的类的对象;注意这个类是

可以动态指定的,如果没有,那么就是默认的BasicDynaBean类。动态指定类是通过反射实现的,程序如下:
//dynaBeanClass为任意的实现了DynaBean接口的类,constructorTypes为这个
//类的构造方法所需要的参数的类型
constructor = dynaBeanClass.getConstructor(constructorTypes);
//constructorValues为构造方法的参数值,实际上它的值为当前的BasicDynaClass
return ((DynaBean) constructor.newInstance(constructorValues));




Commons-Beanutils(四)

一、ConvertUtils 和 ConvertUtilsBean
ConvertUtils 是ConvertUtilsBean类的一个简单封装,即ConvertUtils中的所有方法都是通过直接调用ConvertUtilsBean中的同名方法实现的。如果你需要更复杂的功能,就使用

ConvertUtilsBean,否则使用ConvertUtils。
ConvertUtilsBean 通过一个HashMap管理所有的XXXConverter。这个HashMap的key为XXX的类全名,值为相应的XXXConverter对象。通过deregister()方法,初始化这个HashMap。这个初始

化方法会为每一个XXXConverter类提供一个缺省的值。用户可以动过 setDefaultXXX(...)方法来自行设置XXXConverter对象的缺省值。这个类还提供了convert(...)方法,对 String

value进行相应的转化。

二、PropertyUtils 和 PropertyUtilsBean
PropertyUtils 是PropertyUtilsBean类的一个简单封装,同样它的所有方法都是通过直接调用PropertyUtilsBean 中同名方法实现的。
PropertyUtilsBean 对DynaBean或者一个java标准Bean中的属性动态的赋值和取值(非通过getXXX和setXXX方法)。
1、这个类支持多层嵌套,比如:XXX[i].YYY(key).ZZZ,那么它会为你得到或者设置ZZZ的属性。
2、所有的set/get方法介绍:
//对XXX(key)格式的name设值
setMappedProperty(Object bean, String name,String key, Object value)
//对XXX[i]格式的name设值
setIndexedProperty(Object bean, String name, int index, Object value)
//对XXX格式的name设值
setSimpleProperty(Object bean, String name, Object value)
//对XXX(key).YYY[i].ZZZ格式的名称设值。注意,name必须要遵照这种格式。
//这个方法实际做的就是以“.”为分隔符,逐层的根据情况分别调用上面的几个方法,
//获取相应的bean。
setNestedProperty(Object bean, String name, Object value)
//它直接调用setNestedProperty方法
setProperty(Object bean, String name, Object value)


3、getPropertyType(Object bean, String name)方法中用来获取Bean的某一个property的类型的代码:
	PropertyDescriptor descriptor = getPropertyDescriptor(bean,name);
	if (descriptor == null) {
		return (null);
	}else if (descriptor instanceof IndexedPropertyDescriptor) {
		return (((IndexedPropertyDescriptor)  :arrow: descriptor).getIndexedPropertyType());
	} else if (descriptor instanceof MappedPropertyDescriptor) {
		return (((MappedPropertyDescriptor) descriptor).getMappedPropertyType());
	} else {
		return (descriptor.getPropertyType());
	}

4、getIndexedProperty(Object bean, String name, int index)
这个方法用来获取一个数组或者一个List中的属性。它会首先看这个bean是否是DynaBean类型的,如果是,再其检查是否有name这个属性,如果有那么就直接调用get(String name, int index)方法返回值;如果不是DynaBean类型,那么就会执行如下方法:
//有没有为数组的某个特定元素取值的方法
if (descriptor instanceof IndexedPropertyDescriptor) {
	Method readMethod = ((IndexedPropertyDescriptor) descriptor).
	getIndexedReadMethod();
	if (readMethod != null) {
		Object subscript[] = new Object[1];
		subscript[0] = new Integer(index);
		return (invokeMethod(readMethod,bean, subscript));
	}
}
// 如果没有,就先取出整个对象
Method readMethod = getReadMethod(descriptor);
if (readMethod == null) {
	throw new NoSuchMethodException("Property '" + name + "' has no getter method");
}
Object value = invokeMethod(readMethod, bean, new Object[0]);
//如果这个对象实际上是一个List,那么调用get()方法
if (!value.getClass().isArray()) {
	if (!(value instanceof java.util.List)) {
	throw new IllegalArgumentException("Property '" + name + "' is not indexed");
} else {
	//get the List's value
	return ((java.util.List) value).get(index);
}
//否则通过Array类提供的相应方法取值
} else {
	//get the array's value
	return (Array.get(value, index));
}


三、BeanUtil 和 BeanUtilBean
BeanUtils 是BeanUtilsBean类的一个简单封装,同样它的所有方法都是通过直接调用BeanUtilsBean 中同名方法实现的。
BeanUtilBean 中大多数核心方法都是通过调用PropertyUtilsBean中的方法实现的。而populate(Object bean, Map properties)是自己实现的,因为这个赋值过程要首先对value进行格

式的转化;这个方法把properties中的key为属性名,value为属性的值,分别对应的设值给bean对象。它通过setProperty(Object bean, String name, Object value)方法实现逐个设值的

。由于此时的value不一定符合bean中name属性的类型,所以首先要把value转换成合适的值,然后再设值。具体的类型转换方法如下:
//这种类型转换的原则是:如果value是String或者String[],那么这个值可能为任意的类型, 
    //需要进行转换。如果为其它的类型,则不进行任何转换。
    if (type.isArray() && (index < 0)) { 
        // 如果是直接对一个数组赋值,则使用convert(String values[], Class clazz)方法转换
        if (value == null) {
            String values[] = new String[1];
            values[0] = (String) value;
            newValue = getConvertUtils().convert((String[]) values, type);
        } else if (value instanceof String) {
            String values[] = new String[1];
            values[0] = (String) value;
            newValue = getConvertUtils().convert((String[]) values, type);
        } else if (value instanceof String[]) {
            newValue = getConvertUtils().convert((String[]) value, type);
        } else {
            newValue = value;
        }
    } else if (type.isArray()) {
        // 如果是对数组的某一个元素赋值,则使用convert(String value, Class clazz)方法转换
        if (value instanceof String) {
            newValue = getConvertUtils().convert((String) value, type.getComponentType());
        } else if (value instanceof String[]) {   
            newValue = getConvertUtils().convert(((String[]) value)[0],type.getComponentType());
        } else {
            newValue = value;     
        }
    } else {                 
        // 否则就是一对一的简单赋值,则使用convert(String value, Class clazz)方法转换
        if ((value instanceof String) || (value == null)) {
            newValue = getConvertUtils().convert((String) value, type);
        } else if (value instanceof String[]) {
            newValue = getConvertUtils().convert(((String[]) value)[0], type);       
        } else if (getConvertUtils().lookup(value.getClass()) != null) {
            newValue = getConvertUtils().convert(value.toString(), type);
        } else {
            newValue = value;}
    } 
分享到:
评论

相关推荐

    commons-beanutils (1.7.0 -1.9.2)6个

    - `commons-beanutils-1.8.0-sources.jar`:这个文件包含了`1.8.0`版本的源代码,对于开发者来说是极其宝贵的资源,可以通过阅读源码理解内部实现,学习如何优雅地处理Bean操作,甚至进行二次开发。 4. **使用场景...

    commons-beanutils-1.8.2-src官方源文件,是你学习beanutils工具的必备资料

    总的来说,"commons-beanutils-1.8.2-src"官方源文件包是学习Java Bean操作的宝贵资源,通过研究源代码,开发者不仅可以掌握BeanUtils的使用,还能进一步提升对Java反射和类型转换的理解,从而提高开发效率和代码...

    commons-beanutils-1.8.3-bin

    在本文中,我们将深入探讨`commons-beanutils-1.8.3-bin`这个版本的特性、使用方法以及常见应用场景。 1. **BeanUtils介绍** Apache Commons BeanUtils库是基于JavaBean规范的,它提供了一系列API,用于简化对Java...

    commons-beanutils

    `commons-beanutils-1.8.3`版本包含了完整的源代码,这对于开发者来说是一份宝贵的资源。通过阅读源码,我们可以了解到BeanUtils如何使用反射API来查找和调用JavaBean的getter和setter,以及如何处理属性名的转换和...

    JavaWeb需要用到的jar包_jar包_javaweb_commons-dbutils-1.3_

    2. **commons-beanutils-1.8.0**: Commons-BeanUtils是Apache的另一个开源组件,主要用于Java对象属性的便捷操作。它提供了对JavaBean属性的反射式访问,使得开发者无需直接调用getter和setter方法,即可实现对象...

    Extjs Tree + JSON + Struts2 示例源代码

    现在我自己做了一个所有源代码的包,供大家下载。 有几点事项请大家注意 1、blogjava的文件上载要求单个文件不能超过4M,所以,我把web-inf目录下的所有jar文件删除了。 所有jar文件的列表是: commons-beanutils-...

    精通Java EE整合应用案例 源代码19章 chat

    含源代码,由于文件大小限制,lib目录下的jar文件已经被删除,需要自己上网下载,列表如下: antlr-2.7.5H3.jar asm.jar aspectjweaver-1.5.2a.jar cglib-nodep-2.1_3.jar commons-beanutils-1.7.1-20061106.jar ...

    commons-validator-1.3.1.zip

    1. **源代码**:`src`目录下包含了所有Validator框架的Java源代码,包括各种验证器类、上下文处理类以及与国际化相关的资源文件。这些源代码提供了详细的实现逻辑,可以帮助开发者理解和定制验证规则。 2. **构建...

    SSH基于Eclipse实现Web层的分页功能源代码

    教学-传智播客-项目视频经典之作巴巴运动网106集-27实现Web层的分页功能源代码 所需要的jar文件: (一)、Hibernate: 位于 "\hibernate-distribution-3.3.2.GA" 目录下的jar文件: hibernate3.jar 位于 "\...

    实现Web层的分页功能源代码

    教学-传智播客-项目视频经典之作巴巴运动网106集-27实现Web层的分页功能源代码 所需要的jar文件: (一)、Hibernate: 位于 "\hibernate-distribution-3.3.2.GA" 目录下的jar文件: hibernate3.jar 位于 "\...

    将Web层分页封装成通用模块源代码

    教学-传智播客-项目视频经典之作巴巴运动网106集-28将Web层分页封装成通用模块源代码 所需要的jar文件: (一)、Hibernate: 位于 "\hibernate-distribution-3.3.2.GA" 目录下的jar文件: hibernate3.jar 位于 "\...

    commons-beanutil-1.7.0-src

    开发者可以通过解压"commons-beanutils-1.7.0-src",阅读源代码来深入了解其内部实现,学习如何使用反射、泛型和异常处理等Java技术,以及如何构建类似的实用工具库。此外,源代码还提供了丰富的注释和示例,有助于...

    SSH基于Eclipse将Web层分页封装成通用模块

    教学-传智播客-项目视频经典之作巴巴运动网106集-28将Web层分页封装成通用模块源代码 所需要的jar文件: (一)、Hibernate: 位于 "\hibernate-distribution-3.3.2.GA" 目录下的jar文件: hibernate3.jar 位于 "\...

    struts-1.2.9相关jar包和源代码

    在给定的压缩包文件中,包含了Struts 1.2.9的jar包和源代码,这将有助于开发者深入理解框架的工作原理,进行定制化开发或问题排查。 1. **Struts框架核心组件**: - `struts-core.jar`:包含Struts框架的核心类和...

    struts文件及源代码

    这个压缩包包含了Struts框架的两个版本,即struts-1.2.9-bin.zip和struts-1.2.9-bin.src,分别提供了编译好的二进制库和原始源代码。 **Struts 1.x 概述** Struts 1.x 是Apache软件基金会下的一个项目,它是MVC...

    struts-1.2.9-lib

    - `commons-beanutils.jar`、`commons-digester.jar`、`commons-fileupload.jar`、`commons-logging.jar`:Apache Commons库,提供各种实用工具和框架所需的依赖。 - `jakarta-regexp.jar`:正则表达式库,用于...

    struts-1.2.8-bin

    1. **lib** 目录:这个目录包含了一系列 Struts 运行时需要的 JAR 文件,如 Struts 核心库、Commons 相关库(如 Commons-logging、Commons-beanutils、Commons-collections 等)以及 Servlet 和 JSP API。...

    Struts实践入门(原创)

    - **jakarta-struts-1.1-b1-src.zip**:包含 Struts 的源代码。 - **jakarta-struts-1.1-b1-lib.zip**:包含 Struts 运行所需的库文件。 ##### 2.2 软件需求 为了能够顺利地使用 Struts 构建 Web 应用程序,还需要...

    struts用到的jar和struts源文件.rar

    这个压缩包“struts用到的jar和struts源文件.rar”显然包含了运行和理解Struts 1.2.9版本所需的核心库以及源代码,这对于开发者来说是一个宝贵的资源。 在Struts 1.2.9中,`struts-1.2.9-lib`目录下的jar文件包含了...

    struts-1.2.9-bin.rar(架包)

    4. **src** 目录:源代码文件可以帮助开发者深入理解Struts的内部实现。这里包含了Struts框架的源码,对于想要进行框架扩展或定制的人来说非常有价值。 5. **web-inf** 目录:在实际部署的Web应用中,`WEB-INF`目录...

Global site tag (gtag.js) - Google Analytics