BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器,由于BeanWrapper接口是PropertyAccessor的子接口,因此其也可以设置以及访问被包装对象的属性值。BeanWrapper大部分情况下是在spring ioc内部进行使用,通过BeanWrapper,spring ioc容器可以用统一的方式来访问bean的属性。用户很少需要直接使用BeanWrapper进行编程。
BeanWrapperImpl类是对BeanWrapper接口的默认实现,它包装了一个bean对象,缓存了bean的内省结果,并可以访问bean的属性、设置bean的属性值。BeanWrapperImpl类提供了许多默认属性编辑器,支持多种不同类型的类型转换,可以将数组、集合类型的属性转换成指定特殊类型的数组或集合。用户也可以注册自定义的属性编辑器在BeanWrapperImpl中。
BeanWrapperImpl类有多个重载方法,下面的构造方法传入一个Object对象,此对象就是被BeanWrapperImpl类所包装的bean
构造方法的实现很简单,第一步在registerDefaultEditors()方法内部设置属性defaultEditorsActive值为true
第二步则调用setWrappedInstance(object)方法,进行初始化以及设置被包装的对象
此方法内部对BeanWrapperImpl类的一些重要属性进行了初始化,并创建了TypeConverterDelegate类的实例作为类型转换处理对象。在此之后,将对被包装bean进行内省分析,内省分析结果保存在cachedIntrospectionResults属性中,此属性是CachedIntrospectionResults类的实例.
CachedIntrospectionResults类用于对对象的Class进行内省分析,保存对象的PropertyDescriptor信息,其静态方法
static CachedIntrospectionResults forClass(Class beanClass)
throws BeansException
在BeanWrapperImpl类中被调用,用于对BeanWrapperImpl类所包装的bean进行内省分析,并返回内省分析结果给BeanWrapperImpl
BeanWrapperImpl类有多个设置bean属性值的重载方法,此处以
public void setPropertyValue(PropertyValue pv)
throws BeansException
方法作为说明。
上述方法根据tokens变量是否为null,有两个不同的分支。其中当tokens为null时,则会对属性名进行递归调用分析处理,返回分析处理后的BeanWrapImpl对象nestedBw。如果nestedBw==this,则会设置pv的resolvedTokens属性值,最后将调用nestedBw对象的设置属性值方法设置属性
getBeanWrapperForPropertyPath方法用于对属性名称(包括多重属性)进行处理,并返回BeanWrapperImpl对象。所支持的属性名称包括:多重属性(以.分隔)、数组集合map key属性(以[]方式)。
在此方法中对嵌套类型的属性进行了分析,首先将处理第一个.前的属性,获取nestedBw对象。然后再调用nestedBw对象的此方法递归处理第一个.后的其它属性,并返回处理结果。
getNestedBeanWrapper(nestedProperty)方法则根据nestedProperty获取嵌套的BeanWrapperImpl对象。
getPropertyNameTokens方法内部用于对属性名全路径中最后一个.后的属性名称分析,返回PropertyTokenHolder对象。
最终的设置属性的操作在此方法内部进行实现,此方法将最原始的属性值经过数组、集合类型属性的处理和类型转换后得到转换后值convertedValue,并从内省信息中获取操作此属性的方法writeMethod,用反射调用writeMethod将参数值convertedValue写入至被包装对象的目标属性中。至此BeanWrapperImpl的对象设值操作处理完成。
BeanWrapperImpl类通过其成员属性提供了一种支持嵌套属性的数据结构,下面是BeanWrapperImpl类的成员:
属性类型及名称 |
说明 |
Object object |
被BeanWrapper包装的对象 |
String nestedPath |
当前BeanWrapper对象所属嵌套层次的属性名,最顶层的BeanWrapper此属性的值为空 |
Object rootObject |
最顶层BeanWrapper所包装的对象 |
Map nestedBeanWrappers |
缓存当前BeanWrapper的下一层属性的nestedPath和对应的BeanWrapperImpl对象,此BeanWrapperImpl所包装的对应是属性nestedPath的值 |
例如有类:
Class Employee
{
Company company;
Card card;
String name;
String id;
get/set方法
}
Class Company
{
String companyName;
Map<String,String> attrs;
get/set方法
}
Class Card
{
………….
}
嵌套属性:employee.company.attrs[“location”]
最顶层的BeanWrapper是employeeBeanWrapper,其包装的对象是employeeObj,nestedPath为空,rootObject也是employObj, employeeBeanWrapper里的nestedBeanWrappers则将包含以下的键值对:
“company”---àcompanyBeanWrapper
“card” ---àcardBeanWrapper
对于对象companyBeanWrapper,则其包装的对象则是companyObj,其nestedPath的值为company,rootObject为employeeObj, nestedBeanWrappers里面的值为空。
BeanWrapperImpl在调用方法
protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath)
分析employee.company.attrs[“location”]属性值时,将先处理第一个点之前的属性employee得到顶层的BeanWrapper nestedBw,再调用nestedBw. getBeanWrapperForPropertyPath()方法递归处理第一个点后的其它属性,并最终返回所有属性段都分析后所产生的BeanWrapperImpl对象。
属性类型及名称 |
说明 |
String canonicalName |
canonicalName为actualName再加上[key1][key2][key3]..这种形式 保存当前级别属性的实际名称,为[前的字符串 如属性employee.company.attrs[“location”] 在EmployeeBeanWrapperImpl类代表company属性,则canonicalName值为”company” 如在CompanyBeanWrapperImpl类代表attrs中key为location的属性,则其canonicalName为attrs[“location”]
|
String actualName |
保存当前级别属性的实际名称,为[前的字符串 如属性employee.company.attrs[“location”] 在EmployeeBeanWrapperImpl类代表company属性,则actualName值为”company” 如在CompanyBeanWrapperImpl类代表attrs中key为location的属性,则其actualName为”attrs”,取当前属性级别中”[“前面的字符串
|
String[] keys |
代表当前级别属性中所有位于[与]间的key或索引所组成的数组 |
注:“当前级别属性”表示所要访问在属性在属性全路径中位于..之间的值
在此过程中所使用到的一些工具类和主要方法如下:
org.springframework.beans.PropertyAccessorUtils 用于分析属性名称的工具类,提供分析嵌套属性、集合属性(包括.[]等)的一些工具方法。
出自于http://blog.csdn.net/zhiweianran/article/details/7919129