撸一撸Spring Framework-IoC-BeanWrapper

BeanDefinition一文中我们说过,InstantiationStrategy实例化出的bean只是一个半成品,Spring将半成品的bean交给BeanWrapper,让其负责bean的属性填充工作

不论bean的属性是什么类型,通过xml定义bean时,只能使用字符串字面量来对属性赋值,BeanWrapper首先要将字符串字面量转换为bean属性实际对应的类型,然后通过反射的方式给bean赋值。BeanWrapper的继承结构如下:

重点关注标红的几个组件,TypeConverter、PropertyEditorRegistry、PropertyAccessor是BeanWrapper的三个顶级接口,而PropertyEditor和PropertyEditorSupport比较特殊,是JavaBean规范定义的接口,通过组合的方式被引入Spring体系中

PropertyEditor:属性编辑器,sun制定的JavaBean规范很大程度上是为IDE准备的(基于java开发的IDE),IDE通过PropertyEditor让开发人员使用可视化的方式设置组件的属性,类似下面这种效果,其实就是为某个JavaBean中一个名叫editor的属性赋值

在spring中,对PropertyEditor的用法和传统的用于IDE开发时的不同,它没有UI界面,仅负责将配置文件中的字符串字面量转换为bean属性对应值,比如我们定义了一个名为“people”的<bean>,其中包含三个property,PropertyEditor要做的就是将"1001","zhang san"+"li si"、D:\people\images\123.png"转换为Long、List<String>、File类型

<bean id="people" class="com.example.spring.entity.People" >
  <!--对应 Long id-->
  <property name="id" value="123"/>
  <!--对应 List<String> usedNames-->
  <property name="usedNames">
     <list>
        <value>zhang san</value>
        <value>li si</value>
     </list>
  </property>
  <!--对应 File idCardImage-->
  <property name="idCardImage" value="D:\people\images\123.png"/>
</bean>

java为PropertyEditor提供了一个默认实现PropertyEditorSupport,一般情况下,用户可以通过扩展它实现自己的属性编辑器,Spring就是通过这种方式为常见的属性类型都实现了默认的属性编辑器,其中包括:

  • 基础类型:boolean、byte、short、int、Integer、Long等
  • 集合类:Collection、Set、List、Map等
  • 资源类:Class、File、InputStream、Properties、Resource等

PropertyEditorRegistry:作为PropertyEditor的注册中心,提供了注册、查找PropertyEditor的能力。其子类PropertyEditorRegistrySupport中,维护了两个包含PropertyEditor的Map属性,分别用于管理上述各种类型默认的PropertyEditor、以及用户自定义的PropertyEditor。此外,PropertyEditorRegistry还维护了一个ConversionService对象,ConversionService的功能与PropertyEditors一致,用户可以实现自己的ConversionService,并通过setConversionService方法将其交给PropertyEditorRegistrySupport管理,最终执行属性类型转换的组件就从这三者中选出

private Map<Class<?>, PropertyEditor> defaultEditors;
private Map<Class<?>, PropertyEditor> customEditors;
private ConversionService conversionService;

TypeConverter:类型转换器,是类型转换的入口接口,定义了多个重载的类型转换方法

<T> T convertIfNecessary(Object value, Class<T> requiredType);
。。。其他重载的convertIfNecessary方法

convertIfNecessary方法将值转换为任何指定类型,TypeConverter的实现类是TypeConverterSupport,TypeConverterSupport同时还继承于PropertyEditorRegistrySupport,在其convertIfNecessary方法的实现中,会通过父类PropertyEditorRegistrySupport查找类型转换组件,优先级从高到低分别是从customEditors中获取自定义PropertyEditor、使用ConversionService、从defaultEditors中获取默认PropertyEditor。默认情况下(用户没有自定义PropertyEditor和ConversionService),会获取到默认PropertyEditor,并调用它的setAsText方法完成转换,然后通过它的getValue方法拿到转换后的结果。拿上面例子中的<property name="idCardImage" value="D:\people\images\123.png"/>转换为File这个case 来说,最终调用大致如下:

PropertyEditor fileEditor= new FileEditor();
fileEditor.setAsText("D:\\people\\images\\123.png");
File file=(File) fileEditor.getValue();

PropertyAccessor:属性访问器,定义了各种访问访问bean属性的方法,如:

Class<?> getPropertyType(String propertyName);
TypeDescriptor getPropertyTypeDescriptor(String propertyName);
Object getPropertyValue(String propertyName);
void setPropertyValue(String propertyName, @Nullable Object value);

在将字符串字面值转换为属性类型值后,还要考虑如何将其赋值给bean对象,这个工作就由PropertyAccessor负责,最终实现依赖于java.lang.reflect包,就不再赘述了

猜你喜欢

转载自blog.csdn.net/wb_snail/article/details/121570120