PropertyEditorRegistry

PropertyEditorRegistry 接口的名字虽然和 org.springframework.beans.PropertyEditorRegistrar 接口名字很像,但是功能完全不一样;因为这个接口才是真正注册 Class 和 PropertyEditors 映射关系的,而这些映射关系都会保存到子类 PropertyEditorRegistrySupport 的缓存中。

public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
    private Map<Class<?>, PropertyEditor> defaultEditors;
    private Map<Class<?>, PropertyEditor> overriddenDefaultEditors;
    private Map<Class<?>, PropertyEditor> customEditors;

getDefaultEditor

通过 Class 获取默认属性编辑器,默认是指 Java 中常用数据类型的编辑器,例如:

  • char[]
  • boolean
  • Double
  • BigDecimal
  • List
  • File
  • Locale
  • ...

该方法当中使用了两个缓存 defaultEditors 和 overriddenDefaultEditors,其中 defaultEditors 缓存是 createDefaultEditors 方法赋值的,赋值后就不会更改了。

但是 overriddenDefaultEditors 缓存是用来覆盖 defaultEditors 缓存的,而 overrideDefaultEditor 缓存是通过 overrideDefaultEditor 方法添加数据的,具体可以查看 PropertyEditorRegistrar但是要注意:这里覆盖是使用另一个 Map 集合,而不是直接修改对应的值(为什么这样做我也没想明白)

当该方法被调用时,首先查找 overriddenDefaultEditors 缓存,没找到才会查找 defaultEditors 缓存,还没有找到就会返回 null。

registerCustomEditor

你可以调用这个方法向 customEditors 缓存中,注册自定义属性编辑器;也可以调用 getCustomEditor 方法获取对应的属性编辑器。

注意 getCustomEditor 方法在查找对应的属性编辑器时,如果在 customEditors 缓存中没有找到,那么就会迭代这个缓存并查找 Class 的父级或接口是不是指定的类型

private PropertyEditor getCustomEditor(@Nullable Class<?> requiredType) {
    for (Map.Entry<Class<?>, PropertyEditor> entry : this.customEditors.entrySet()) {
        Class<?> key = entry.getKey();
        if (key.isAssignableFrom(requiredType)) {

注册自定义属性编辑器

注册自定义属性编辑器有两种方式,直接注册属性编辑器和通过属性编辑注册器注册;这两种方式都必须实现一个 属性编辑器,关于属性编辑注册器可以查看 PropertyEditorRegistrar

第一种方式,直接注册属性编辑器:

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="customEditors">
    <map>
        <entry key="com.xxx.User">
            <bean class="com.xxx.UserPropertyEditor"/>
        </entry>
    </map>
  </property>
</bean>

第二种方式,通过属性编辑注册器注册属性编辑器:

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="propertyEditorRegistrars">
    <list>
      <bean class="com.xxx.UserEditorRegistrar"/>
    </list>
  </property>
</bean>

官方推荐使用第二种方式,因为第二种方式在每次使用时都会创建一个新的属性编辑器实例,这样可以避免处理同步问题。

CustomEditorConfigurer

这个类就是用来注册属性编辑器的。

public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered {
    private PropertyEditorRegistrar[] propertyEditorRegistrars;
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (this.propertyEditorRegistrars != null) {
            for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
                beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
            }
        }
        if (this.customEditors != null) {
            this.customEditors.forEach(beanFactory::registerCustomEditor);
        }
    }

如果你不是使用 xml 配置的,那么可以继承 CustomEditorConfigurer 并向 propertyEditorRegistrars 属性中添加数据。

参考文章

Spring Property Editor – CustomEditorConfigurer Example

posted @ 2022-06-11 23:26  不是很聪明  阅读(46)  评论(0)    收藏  举报