spring 源码研究---bean包--BeanWapper TypeCoverter PropertyEditorRegistrySupport BeanInfo PropertyValue

来源:互联网 发布:大学o2o源码 编辑:程序博客网 时间:2024/05/17 05:08


#####################   PropertyValue  ############################
AttributeAccessor定义了访问属性访问器
AttributeAccessorSupport使用hash表来管理属性访问器
BeanMetadataElement接口携带了包含bean元数据元素的source对象
BeanMetadataAttribute类持有bean对象中一个key/value属性,跟踪source对象
BeanMetadataAttributeAccessor继承了AttributeAccessorSupport类,实现了BeanMetadataElement接口,
它不仅拥有属性访问器,它把属性值设置为BeanMetadataAttribute类型,把key设置为BeanMetadataAttribute的key,它还可以跟踪source对象
PropertyValue继承自BeanMetadataAttributeAccessor
保存bean对象中的信息及值,使用一个对象,而不是让所有属性保存在Map对象中,它允许了更大的灵活性,并且能都处理索引属性来优化
它可以是简单的包含属性,不需要进行解析后放入        
PropertyValues接口持有一个或多个PropertyValue对象,通常更新指定的bean。
MutablePropertyValues实现了PropertyValues接口。
把所有PropertyValue放入了List集合中,可以当作集合来管理PropertyValue对象,
它提供了构造器可以对来自List Map PropertyValues等持有PropertyValue对象的集合中进行深度拷贝。

/**
 *################################ BeanWrapper#############################
 * PropertyAccessor接口定义了class类中字段的访问和设置功能
 * 判断该字段是否支持读 写
 * 通过字段名取得对应的类型
 * 通过字段名得到对应的对象
 * 通过字段名得到类型描述TypeDescipter
 * 通过name,vaule或Map或PropertyValue或PropertyValues来设置字段值
 * 在设置PropertyValues集合属性时,可以设置是否忽略不需要的元素或无法验证的元素
 *
 * ConfigurablePropertyAccessor接口继承了PropertyAccessor接口 PropertyEditorRegistry接口 和TypeConverter接口
 * 它就包含属性访问器、编辑器管理、及类型转换功能
 * 它自己设置配置转换器服务ConversionService
 * 设置了是否需要提取编辑器设置的旧值
 * AbstractPropertyAccessor抽象类实现了TypeConverterSupport和ConfigurablePropertyAccessor
 * 定义了访问器的set get 主要结构,主要的实现有子类完成,这是典型的模板方法。
 *
 * 定义bean对象,
 * 定义bean对象的.之前的根路径对象,如果对象是集合,定义每个元素在集合中的路径
 * 定义了缓存当前访问器的map key nestedPath value是该类下的下一个访问器
 * 构造器
 * 1.是否使用默认的编辑器
 * 2.默认构造函数为使用默认的编辑器
 * 3.给定对象或类型
 * 构造器根据设定的值构造该对象
 * 可以访问该对象实例
 * 可以访问该对象类型
 * 可以访问该对象在元素集合中的位置属性
 * 可以访问该对象访问器的根对象 .最前面的对像及根对象类型
 *
 *
 * 设置值 String propertyName, Object value
 * 1:通过属性名转换为PropertyTokenHolder对象,这个对象包含了
 * actualName真实的对象名如果是集合就是[]前面的对象名,否则是propertyName
 * 如果是集合canonicalName=actualName[key1][key2]否则是propertyName
 * 包含了keys的集合 key1 key2
 * 然后使用这actualName得到PropertyHandler 这个功能有子类实现
 * PropertyHandler是什么呢?
 * PropertyHandler是定义在AbstractNestablePropertyAccessor内部的一个抽象类
 * 它用于持有一个对象属性的各种资源,它的大部分实现是有子类完成的,有见模板方法
 * 属性资源是通过反射还是Javabean方式获取有子类来实现。
 * 有了对象实例和类型就可以通过反射的取的属性相关的信息 子类来实现 填充对象
 * 继续回到上面得到PropertyHandler以后就可以取的该属性的值,
 * 如果子类没有实现 则创建一个新的对象返回
 * 然后创建一个AbstractNestablePropertyAccessor或则从缓存中取的
 * 递归查找每个访问器。
 * 查找到放入PropertyValue,包含了PropertyTokenHolder,如果是数组就可以定位该地方设置值了
 *
 * 查找
 * mb[0].bean1.bean2.order[2]
 * //首先根据 mb[0].bean1.bean2.order[2] 属性名,取mb字段通过反射取的值,
//然后取的集合中的第0个对象这里就叫root对象,
//使用参数root对象、下一个属性路径bean1.bean2.order[2]和父访问器dfa 来构造一个新的访问器
//递归以上方式,最后取的值。
 *
 * BeanWrapperImpl和DirectFieldAccessor都实现了AbstractNestablePropertyAccessor
 * DirectFieldAccessor使用了反射的方式设置和取值的
 * BeanWrapperImpl使用的时Javabean技术访问BeanInfo的PropertyDescripter
 *
 */
################### BeanInfo ###################################################
//创建BeanInfo使用了简单工厂BeanInfoFactory,
//由子类ExtendedBeanInfoFactory实现,该类并且继承了排序接口Ordered对BeanInfo设置序号
//ExtendedBeanInfoFactory内部使用了ExtendedBeanInfo来创建BeanInfo
//ExtendedBeanInfo使用了装饰器模式对从Introspector#getBeanInfo得到BeanInfo对象进行了装饰。
//装饰原因:主要对java bean支持写方法即set方法的返回值为void不支持set方法的返回值为非void
//由于需要创建模式等,会返回当前对象所以需要支持该方式。

//注意ExtendedBeanInfo只支持此方式

/*例如:
 * public Bean setFoo(Foo foo) {
 *         this.foo = foo;
 *         return this;
 * }
 *ExtendedBeanInfo继承BeanInfo 通过构造器委托该对象实现大部分方法,并包装了PropertyDescriptor[]返回对象
 * 经过包装后的PropertyDescriptor[],很好的支持了每个返回值不为void的set方法取的的PropertyDescriptor对象
 * 装饰过程:
 * 1.拷贝BeanInfo对象的PropertyDescriptor到Set集合中,
 * 2.循环MethodDescriptor[]判断方式是否符合 set(参数1)或,setXx(参数1,参数2)
 * 1.方法名称字数大于3
 * 2.set开头
 * 3.方法访问权限为public
 * 4.非void或者是静态方法
 * 5.参数为一个 或者如果是数组属性 可以两个参数,但第一个必须是int类型
 *
 * 如果符合截取方法名setXx为xx和第一个参数类型去匹配Set集合中的PropertyDescriptor
 * 是否存在 如果存在,就设置PropertyDescriptor的write方法为该方法。
 * 否则就创建一个PropertyDescriptor放入Set集合中。
 * 最后在重写public PropertyDescriptor[] getPropertyDescriptors()时,
 * 把Set集合返回。
 * 经过包装spring可以只支持set方法就取的PropertyDescriptor
 * 说了这么多,BeanInfo到底怎么创建的?
 * 是由Introspector.getBeanInfo(xx.class)方法创建
 * 由于工厂只创建包含典型的set方法返回的非void类型,
 * 所以如果是正常的就是用Introspector.getBeanInfo(xx.class)创建Beanfo
 *
 * 在类中,如果是泛型属性会存在一个set类型的桥梁方法
 * 需要对BeanInfo中PropertyDescriptor[]数组的元素做写方法和读方法做处理
 * GenericTypeAwarePropertyDescriptor继承了PropertyDescriptor类,
 * 它对写方法和读方法出现的桥梁方法做了处理,并兼容了set方法比如set方法是private的。
 * GenericTypeAwarePropertyDescriptor作为一个PropertyDescriptor放入缓存map中。
 * key是属性名字,value就是这个GenericTypeAwarePropertyDescriptor对象
 * 可以使用map得到集合 数组或使用属性名查询PropertyDescriptor
 * 通过Class对象获得查询包装后的适合spring的BeanInfo及PropertyDescriptor[]
 * 对于这些结果需要用缓存存起来,因为访问底层是有消耗的。
 * CachedIntrospectionResults就是用来缓存内省结构信息,它接受一个或多个类加载器
 * 来加载class类型。
 * 如果给定的Class类型在它接受的类加载器中(或者Class类型类加载器与CachedIntrospectionResults对应的类加载器属于同一类加载器或是同一父类加载器)
 * ,则把Class对象作为key CachedIntrospectionResults作为值
 * 缓存在一个线程安全强引用的map中(strongClassCache)。
 * 否则缓存在另一个线程安全弱引用的map中(softClassCache)。
 * 通过CachedIntrospectionResults的静态方法 static CachedIntrospectionResults forClass(Class<?> beanClass)
 * 首先从强引用缓存中取,没有则然后从弱引用中取,如何还没有则使用,则new CachedIntrospectionResults对象创建BeanInfo信息。
 * 放入缓存,返回CachedIntrospectionResults,就可以得到beanInfo信息 或类加载,或PropertyDescriptor[]等信息。
 * 大概数据结构:
 *  * -Class<?>{
*                         CachedIntrospectionResults{
*                             ClassLoader{
*                                 ClassLoader1,
*                                 ClassLoader2,
*                             }
*                             BeanInfo,
*                             PropertyDescriptors[
*                                PropertyDescriptor,
*                                PropertyDescriptor
*                            ],
*                            TypeDescriptor{
*                                PropertyDescriptor:TypeDescriptor,
*                                PropertyDescriptor:TypeDescriptor,
*                            }
*                         },
*                       }

/**########################### PropertyEditorRegistry  ##############################
 * PropertyEditorRegistry接口定义了PropertyEditor编辑器的注册服务
 * 主要功能为注册定制的PropertyEditor编辑器和查找PropertyEditor编辑器
 * 以PropertyEditor的实现类Class为key,编辑器为value放入字典中。
 * 对于集合和数组中对应的元素则以该元素的属性路径及propertyPath为key,
 * value为(该集合实现了Class为key,该元素的编辑器为value)放入字典中, propertyPath=items[n]
 * 对于集合每个元素都有单一的注册编辑器,不注册集合或数组相同元素为同一编辑器
 * 如果要注册items[n].quantity中的所有元素则使用items.quantity
 *
 *
 * PropertyEditorRegistrySupport类实现了PropertyEditorRegistry接口
 * 它提供了默认编辑器注册和定制编辑器
 * 它使用了5种注册表
 * 1.默认注册表
 * 包含了大量spring定义的属性编辑器,有基本包装类型,集合及常用的类属性编辑器
 * 2.覆盖默认的注册表
 * 如果默认注册表种的编辑器和自定义的编辑器有重复则优先使用自定义的
 * 3.定制注册表
 * key为编辑器实现PropertyEditor的Class类,value为实现对象
 * 4.定制propertyPath注册表
 * propertyPath是集合对象中元素的属性路径作为key 比如:item[5]
 * (key为编辑器实现PropertyEditor的Class类,value为实现对象)
 * (使用CustomEditorHolder对象持有)作为propertyPath的value.
 * 5.用于缓存定制注册表
 * 加快注册表访问速度,专门为定制注册表做了一个缓存。
 *
 * 它给子类提供了注册默认编辑器的方法
 * 它提供了转换类型服务
 * 它提供了用户可以激活默认编辑器的功能,默认没有激活
 * 它通过给定的Class编辑器和propertyPath路径来注册到不同的注册表中(放入map中)
 * 它通过给定的Class和propertyPath查找注册表中的编辑器返回
 *
 */
/**########################## TypeCoverter ####################
 * spring封装了自动的转换的功能,结合了TypeCoverter
 * TypeConverter接口定义了类型转换的方法,通常的(但不需要的)子类也要实现PropertyEditorRegistry
 * 转换通常使用PropertyEditor的setAsText或者使用spring的ConversionService转换服务
 * 通常把一个对象转化为给定的类型
 * TypeConverterSupport实现了TypeConverter和PropertyEditorRegistry它没有做实质性的实现,
 * 直接把实现委托给TypeConverterDelegate类来处理
 * TypeConverterDelegate它认认真真的完成委托人的转换类型任务。它需要有属性注册服务PropertyEditorRegistrySupport的支持
 * BeanWrapperImpl和SimpleTypeConverter子类把自己作为PropertyEditorRegistrySupport委托给TypeConverterDelegate处理
 * 因为不同的实现有不同编辑属性注册表
 *
 * convertIfNecessary(String propertyName, Object oldValue, Object newValue, Class<T> requiredType,
 * TypeDescriptor typeDescriptor)
 * propertyName 注册表中的集合属性地址
 * oldValue
 * newValue    要转换的对象
 * requiredType  转换后需要的类型
 * typeDescriptor 转换后的类型描述,比如有annotation的方法参数或字段包含的信息
 *===转换器转换
 * 通过propertyName requiredType来查找一个属性编辑器
 * 取的注册编辑器服务设置的ConversionService转换对象
 * 如果属性编辑器为空并且ConversionService不为空并且newValue不为空并且typeDescriptor不为空
 * 则使用typeDescriptor取的newValue的TypeDescriptor,
 * 使用ConversionService.convert判断要转换对象的TypeDescriptor和目标typeDescriptor能否转换
 * 如果能转换直接使用ConversionService转换返回转换类型
 *
 * ==编辑器转换及集合转换
 * 否则使用编辑器转换
 *    newValue requiredType typeDescriptor         
 * 1.String --    集合    - > 枚举             String[]  
 * 如果编辑器不为空或者newValue不是来自于requiredType
 *         如果requiredType是一个集合类型,newValue为一个String类型,并且typeDescriptor是枚举类型
 *         则使用,分割String类型后作为String数组设置newValue为String数组,使用编辑器进行编辑
 *      把newValue进行编辑器先转换一次
 *
 * 如果requiredType不为空,并且编辑后convertedValue不为空,
 * 1.convertedValue是Object类型直接返回
 * 2.requiredType是数组
 * 3.convertedValue是集合
 * 4.convertedValue是Map
 * 5.convertedValue是数组类型,就包含一个元素,就返回该元素
 * 6.requiredType如果是String类型,包装convertedValue作为对象返回
 * 7.如果convertedValue是String 但requiredType不是String的实例
 * 试着使用requiredType的构造函数(String convertedValue)创建对象实例
 * 或者requiredType是Number类型的就转换
 * 或者转换为枚举
 *
 *数组的转换:
 *    如果转换对象类型为Collection
 *    根据转换对象集合,创建一个需要类型数组
 *    循环转换对象集合,使用上面的convertIfNecessary方法来转换,其中propertyName=propertyName[i]
 *    这个可以用来查询编辑器注册表,需要类型数组添加每一个转换后的返回元素
 *     返回这个类型数组
 *  如果是转换类型是数组, 并且需要类型也是该数组,并且编辑器中不包含数组中元数的转换器,则直接返回该转换数组
 *  否则循环转换
 *  
 *  如果 转换对象就一个对象 直接创建一个需要类型的数组把这个转换对象添加进入返回
 *  
 *集合和数组相似
 *
 * SimpleTypeConverter设置了默认编辑器注册表,并且把转换类型任务委托给TypeConverterDelegate处理
 *
*/


0 0
原创粉丝点击