Spring官网阅读(十四)Spring中的BeanWrapper及类型转换(1)

简介: BeanWrapper是Spring中一个很重要的接口,Spring在通过配置信息创建对象时,第一步首先就是创建一个BeanWrapper。这篇文章我们就分析下这个接口,本文内容主要对应官网中的3.3及3.4小结

接口定义

// Spring低级JavaBeans基础设施的中央接口。通常来说并不直接使用BeanWrapper,而是借助BeanFactory或者DataBinder来一起使用,BeanWrapper对Spring中的Bean做了包装,为的是更加方便的操作Bean中的属性
public interface BeanWrapper extends ConfigurablePropertyAccessor {
  void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
  int getAutoGrowCollectionLimit();
  // 获取包装的Bean
  Object getWrappedInstance();
  // 获取包装的Bean的class
  Class<?> getWrappedClass();
  // 获取所有属性的属性描述符
  PropertyDescriptor[] getPropertyDescriptors();
  // 获取指定属性的属性描述符
  PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
}

这里需要解释一个概念,什么是属性描述符?

PropertyDescriptor:属性描述符,能够描述javaBean中的属性,通过属性描述符我们能知道这个属性的类型,获取到操纵属性的方法(getter/setter)


继承关系


微信图片_20221113102719.png

BeanWrapper的子类只有一个:BeanWrapperImpl,它继承了ConfigurablePropertyAccessor,这个接口的主要功能是进行属性访问,同时它又有三个父接口,接下来我们一一分析他们的功能。


接口功能


1、PropertyEditorRegistry(属性编辑器注册器)


接口定义

// 这个接口的功能很简单,就是用来注入属性编辑器(PropertyEditor),那么什么是PropertyEditor呢?
public interface PropertyEditorRegistry {
  void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor);
  void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor);
  @Nullable
  PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath);
}

PropertyEditor


概念

PropertyEditor是JavaBean规范定义的接口,这是java.beans中一个接口,其设计的意图是图形化编程上,方便对象与String之间的转换工作,而Spring将其扩展,方便各种对象与String之间的转换工作。


Spring中对PropertyEditor使用的实例


1.我们在通过XML的方式对Spring中的Bean进行配置时,不管Bean中的属性是何种类型,都是直接通过字面值来设置Bean中的属性。那么是什么在这其中做转换呢?这里用到的就是PropertyEditor

2.SpringMVC在解析请求参数时,也是使用的PropertyEditor


Spring内置的PropertyEditor

微信图片_20221113103012.png


2、PropertyAccessor(属性访问器)


接口定义

public interface PropertyAccessor {
    // 嵌套属性的分隔符,比如"foo.bar"将会调用getFoo().getBar()两个方法
  String NESTED_PROPERTY_SEPARATOR = ".";
  char NESTED_PROPERTY_SEPARATOR_CHAR = '.';
   // 代表角标index的符号  如person.addresses[0]  这样就可以把值放进集合/数组/Map里了
  String PROPERTY_KEY_PREFIX = "[";
  char PROPERTY_KEY_PREFIX_CHAR = '[';
  String PROPERTY_KEY_SUFFIX = "]";
  char PROPERTY_KEY_SUFFIX_CHAR = ']';
    // 该属性是否可读/可写,不存在则返回false
  boolean isReadableProperty(String propertyName);
  boolean isWritableProperty(String propertyName);
    // 获取/设置属性的方法,基本见名知意
  @Nullable
  Class<?> getPropertyType(String propertyName) throws BeansException;
  @Nullable
  TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;
  @Nullable
  Object getPropertyValue(String propertyName) throws BeansException;
  void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException;
  void setPropertyValue(PropertyValue pv) throws BeansException;
  void setPropertyValues(Map<?, ?> map) throws BeansException;
  void setPropertyValues(PropertyValues pvs) throws BeansException;
  void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown)
      throws BeansException;
  void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
      throws BeansException;
}

这里需要解释一个概念,什么是PropertyValue?


当设置属性值时,少不了两样东西:


1.属性访问表达式:如listMap[0][0]

2.属性值:

ProperyValue对象就是用来封装这些信息的。如果某个值要给赋值给bean属性,Spring都会把这个值包装成ProperyValue对象。


3、TypeConverter(类型转换器)


接口定义

// 定义了进行类型转换时的一些规范,就像名字定义的那样,主要用来做类型转换
public interface TypeConverter {
    // 将指定的值转换成指定的类型
  @Nullable
  <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType) throws TypeMismatchException;
    // 相对于上面这个方法下面这个三种方法能处理转换过程中的泛型
  @Nullable
  <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
      @Nullable MethodParameter methodParam) throws TypeMismatchException;
  @Nullable
  <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType, @Nullable Field field)
      throws TypeMismatchException;
  default <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
      @Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
    throw new UnsupportedOperationException("TypeDescriptor resolution not supported");
  }
}

4、ConfigurablePropertyAccessor

public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter {
  // ConversionService:进行转换的业务类,转换系统的入口
  void setConversionService(@Nullable ConversionService conversionService);
  @Nullable
  ConversionService getConversionService();
    // 进行属性编辑是是否返回旧的值
  void setExtractOldValueForEditor(boolean extractOldValueForEditor);
  boolean isExtractOldValueForEditor();
    // 当设置(dog.name)这种嵌套属性的情况下,如果dog属性为null是否会报错
    // 为true的话不会,为false会抛出NullValueInNestedPathException
  void setAutoGrowNestedPaths(boolean autoGrowNestedPaths);
  boolean isAutoGrowNestedPaths();
}

从上面可以看到,BeanWrapper接口自身对Bean进行了一层包装。另外它的几个通过间接继承了几个接口,所以它还能对Bean中的属性进行操作。PropertyAccessor赋予了BeanWrapper对属性进行访问及设置的能力,在对Bean中属性进行设置时,不可避免的需要对类型进行转换,而恰好PropertyEditorRegistry,TypeConverter就提供了类型转换的统一约束。


在了解了接口之后,我们接下来看看它的唯一实现类BeanWrapperImpl


相关文章
|
3月前
|
Java 应用服务中间件 Spring
Spring5源码(50)-SpringMVC源码阅读环境搭建
Spring5源码(50)-SpringMVC源码阅读环境搭建
65 0
|
10月前
|
Java Nacos Spring
Nacos spring-cloud 版本没找到共享配置文件的说明,Nacos服务中共享,并且可以被多个应用获取和使用。这个在官网哪里有说明啊
Nacos spring-cloud 版本没找到共享配置文件的说明,Nacos服务中共享,并且可以被多个应用获取和使用。这个在官网哪里有说明啊
60 1
|
2月前
|
存储 Java 程序员
Spring 注册BeanPostProcessor 源码阅读
Spring 注册BeanPostProcessor 源码阅读
|
Java 中间件 Maven
Spring 6 源码编译和高效阅读源码技巧分享
Spring 6 源码编译和高效阅读源码技巧分享
|
Java API Spring
Spring 6 源码编译和高效阅读源码技巧分享
Spring 6 源码编译和高效阅读源码技巧分享
|
Java Spring
Spring 官网无法查看的版本依赖如何查看?
Spring 官网无法查看的版本依赖如何查看?
63 0
|
前端开发 Java Spring
《Spring MVC》 第六章 MVC类型转换器、格式化器
《Spring MVC》 第六章 MVC类型转换器、格式化器
175 0
|
Java 容器 Spring
【Spring源码阅读】IOC容器的依赖注入
SpringIOC容器的依赖注入发生在用户第一次向IOC容器获取Bean时。除在BeanDefinition中设置lazy-init属性让容器完成bean的预实例化。我们在前面《Spring-IOC容器接口设计与功能》中曾讲过,容器BeanFactory通过getBean方法获取Bean。所以这篇文章,我们将从getBean()方法入手分析SpringIOC容器依赖注入的过程。
|
XML Java 数据格式
Spring源码阅读-IOC容器初始化过程
Spring IOC容器的初始化过程:Resource定位,BeanDefinition载入,向IOC容器注册BeanDefinition。整个过程由refresh()方法触发,三个过程由不同的模块完成,使用户更加灵活的对这三个过程剪裁和扩展。
127 0
|
XML 缓存 JSON
Spring MVC 阅读官方文档知识点总结
Spring MVC 阅读官方文档知识点总结
162 8