Spring源码解读之BeanWrapperImpl结构解读

   个人理解:在spring中,关于Bean赋值的类与接口主要是BeanDefinition接口、BeanWrapper接口与它们的实现类,同时这两个接口应该算是在spring体系中承上启下的作用了,要理解整个spring的体系,这两个接口还是非常重要的,因为它们代表的是数据部分、而所有逻辑都是用来处理数据的。

首先是整个关系图:

      Spring源码解读之BeanWrapperImpl结构解读_第1张图片

然后从低到到高依次解析

    首先是接口PropertyEditorRegistry

                 Spring源码解读之BeanWrapperImpl结构解读_第2张图片

       通过它的方法可知其是用来注册以及发现CustomEditor。也就是自定义的属性编辑器。

 在其入参中,我们可以看到有一个参数PropertyEditor,这个接口是jdk的原生接口,并不是Spring的,其作用是用来做类型转换的。在Spring平时的使用中常见有将前端传的字符类型转换为时间的,其实你在一个@RequestMapper接口的入参中用其它类型的做接收参数如Integer、Short等,如:

      Spring源码解读之BeanWrapperImpl结构解读_第3张图片

对于Spring接收到的前端参数来说,前端传入的都是字符串、spring帮你做了转换,例如转换为List、Integer等。这一部分的功能我们可以在PropertyEditor的实现类PropertyEditorRegistrySupport中看到:

        Spring源码解读之BeanWrapperImpl结构解读_第4张图片

 这里我们需要关注两个全局变量,defaultEditors、customEditors,这两个一个是用来存默认的PropertyEditor、另一个是用来存你自己通过实现接口PropertyEditor接口自定义的PropertyEditor(例如说你自定义的从spring转换为Data,之所以spring转换为时间类型时要你自定义,是因为Spring没有定义默认时间的PropertyEditor,因为时间的格式有多种)。而默认的PropertyEditor我们可以看到有加载了43个,其中一部分:Spring源码解读之BeanWrapperImpl结构解读_第5张图片

 

  接下来是另两个接口:PropertyAccessor、与TypeConverter,即属性寄存器、类型转换器,这两个需要配合使用的。因为你要进行类型转换肯定是要用到对应的属性。

      TypeConverter的方法:

             Spring源码解读之BeanWrapperImpl结构解读_第6张图片

    即如果需要就进行类型转换,而要了解PropertyAccessor接口你需要知道java内省的概念,可以看我前面的博文:         https://blog.csdn.net/qq_25179481/article/details/96737649。

   之后是类TypeConverterSupport

         Spring源码解读之BeanWrapperImpl结构解读_第7张图片

   类型转换支持类,这个类的作用应该是组合一个功能做类型装换的功能,首先需要判断就是需不需要做类型转换,所以要实现typeConverter接口。如果需要,就要转换成对应的类型需要什么工具,这个工具就是PropertyEditorRegistry接口了。

  再之后就是ConfigurablePropertyAccessor接口,其关键就是组合:PropertyAccessor、与TypeConverter,因为这两个也是我前面说的,但其实你要进行类型转换。首先你需要对应的属性名。以及属性值,这部分由PropertyAccessor接口提供、然后你需要判断现在的属性值的类型是不是对应对象的属性 需要的类型,这部分由PropertyAccessor接口提供,如果需要这时候就需要一个工具去进行类型转换,这部分就需要PropertyEditorRegistry接口,所以现在就需要整合TypeConverterSupport与ConfigurablePropertyAccessor了,通过类AbstractPropertyAccessor,这样他们就能实现整个赋值过程了。

     Spring源码解读之BeanWrapperImpl结构解读_第8张图片

我们来看AbstractPropertyAccessor类的方法:

          Spring源码解读之BeanWrapperImpl结构解读_第9张图片

    由于AbstractPropertyAccessor已经有赋值的三块积木了,现在可以组合这三块积木来构成赋值的完整过程了,可以通过其的方法:

       

@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
   setPropertyValue(pv.getName(), pv.getValue());
}

  来进行赋值操作了,其他几个最终也会转到这个方法上:

      Spring源码解读之BeanWrapperImpl结构解读_第10张图片

    不过这个setPropertyValue(pv.getName(), pv.getValue())方法是一个模板方法:

      

@Override
public abstract void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException;

     这个逻辑是通过AbstractPropertyAccessor的实现类AbstractNestablePropertyAccessor实现的。关于AbstractNestablePropertyAccessor类,其类名有一个词Nestable,百度一下即(嵌套)。因为你的属性名并不是一个简单的private String name,还有List,Map等,spring支持的赋值方式有wrapper.getPropertyValue("nested.prop")、wrapper.setPropertyValue("array[0].prop", "test")、wrapper.getPropertyValue("list[4])等,所以会有一个属性嵌套路径。

     之后要进行赋值的操作了,不过还缺了一块,也就是对象,因为你需要将对应的属性与其值进行对应的转换然后赋值给对象。

   这时候就需要第四块积木:BeanWrapper:

              Spring源码解读之BeanWrapperImpl结构解读_第11张图片

   getWrappedInstance()也就是获取没有进行赋值的初始化对象,getPropertyDescriptor(String propertyName),获取对应属性的PropertyDescriptor来给对象进行赋值。

     好了,现在所有积木都有了,可以进行终极大集合,终于可以自己造一个合适自己的对象了,这一切就交给我们的BeanWrapperImpl。整个的处理逻辑就通过它来处理吧。

你可能感兴趣的:(#,Spring系列,Spring源码,java)