PropertyEditorRegistry 和 PropertyEditorRegistrySupport 源码

半城伤御伤魂 提交于 2020-04-08 10:49:26

  • PropertyEditorRegistry 属性编辑器注册表

    • 封装了注册 JavaBeans PropertyEditors 的方法

      //注册给定类型的所有属性的自定义属性编辑器
      void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor);
      
      //如果属性path是一个array/Collection,这里的requireType应该是其元素的类型
      void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor);
      
      //找到一个指定类型和属性的属性编辑器
      @Nullable
      PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath);
      
  • PropertyEditorRegistrySupport 属性便捷器注册支持

    • 是 PropertyEditorRegistry 的基本实现 , 提供了默认编辑器和自定义编辑器的管理 ,只要担任 BeanWrapperImpl 的基类。

    • 有几个成员变量

      @Nullable
      private ConversionService conversionService;
      
      private boolean defaultEditorsActive = false;
      
      private boolean configValueEditorsActive = false;
      
      @Nullable
      private Map<Class<?>, PropertyEditor> defaultEditors;
      
      @Nullable
      private Map<Class<?>, PropertyEditor> overriddenDefaultEditors;
      
      @Nullable
      private Map<Class<?>, PropertyEditor> customEditors;
      
      @Nullable
      private Map<String, CustomEditorHolder> customEditorsForPath;
      
      @Nullable
      private Map<Class<?>, PropertyEditor> customEditorCache;
      
    • 其中有 关于 ConversionService 的方法

    • /**
       * Specify a Spring 3.0 ConversionService to use for converting
       * property values, as an alternative to JavaBeans PropertyEditors.
       */
      public void setConversionService(@Nullable ConversionService conversionService) {
         this.conversionService = conversionService;
      }
      
      /**
       * Return the associated ConversionService, if any.
       */
      @Nullable
      public ConversionService getConversionService() {
         return this.conversionService;
      }
      
    • 关于默认编辑器方法

      //激活这个注册表实例的默认编辑器,允许懒注册的默认编辑器在需要的时候被注册
      protected void registerDefaultEditors() {
         this.defaultEditorsActive = true;
      }
      //激活配置编辑器,为了配置值。这些编辑器没有被默认注册,因为他们不大适合用于数据绑定。
      public void useConfigValueEditors() {
      		this.configValueEditorsActive = true;
      }
      //重写默认编辑器
      /* 和注册一个自定义编辑器不同,重写完之后还是一个默认编辑器
      * 一个ConversionService会重写这样一个默认编辑器,然而,自定义编辑器通常重写ConversionService
      */
      public void overrideDefaultEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
          if (this.overriddenDefaultEditors == null) {
              this.overriddenDefaultEditors = new HashMap<>();
          }
          this.overriddenDefaultEditors.put(requiredType, propertyEditor);
      }
      //根据属性类型得到默认属性编辑器,如果他们是active的,则懒注册他们
      @Nullable
      public PropertyEditor getDefaultEditor(Class<?> requiredType) {
          if (!this.defaultEditorsActive) {
              return null;
          }
          if (this.overriddenDefaultEditors != null) {
              PropertyEditor editor = this.overriddenDefaultEditors.get(requiredType);
              if (editor != null) {
                  return editor;
              }
          }
          if (this.defaultEditors == null) {
              createDefaultEditors();
          }
          return this.defaultEditors.get(requiredType);
      }
      //创建了许多默认编辑器(在这个注册表实例里)
      private void createDefaultEditors() {
      		this.defaultEditors = new HashMap<>(64);
      
      		// 简单的编辑器,没有参数化的功能
      		// The JDK does not contain a default editor for any of these target types.
      		this.defaultEditors.put(Charset.class, new CharsetEditor());
      		this.defaultEditors.put(Class.class, new ClassEditor());
      		this.defaultEditors.put(Class[].class, new ClassArrayEditor());
      		this.defaultEditors.put(Currency.class, new CurrencyEditor());
      		this.defaultEditors.put(File.class, new FileEditor());
      		this.defaultEditors.put(InputStream.class, new InputStreamEditor());
      		this.defaultEditors.put(InputSource.class, new InputSourceEditor());
      		this.defaultEditors.put(Locale.class, new LocaleEditor());
      		this.defaultEditors.put(Path.class, new PathEditor());
      		this.defaultEditors.put(Pattern.class, new PatternEditor());
      		this.defaultEditors.put(Properties.class, new PropertiesEditor());
      		this.defaultEditors.put(Reader.class, new ReaderEditor());
      		this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
      		this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
      		this.defaultEditors.put(URI.class, new URIEditor());
      		this.defaultEditors.put(URL.class, new URLEditor());
      		this.defaultEditors.put(UUID.class, new UUIDEditor());
      		this.defaultEditors.put(ZoneId.class, new ZoneIdEditor());
      
      		// 集合类的默认编辑器实例
      		// Can be overridden by registering custom instances of those as custom editors.
      		this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
      		this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
      		this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
      		this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
      		this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class));
      
      		// 基本数组的默认编辑器
      		this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
      		this.defaultEditors.put(char[].class, new CharArrayPropertyEditor());
      
      		// The JDK does not contain a default editor for char!
      		this.defaultEditors.put(char.class, new CharacterEditor(false));
      		this.defaultEditors.put(Character.class, new CharacterEditor(true));
      
      		// Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
      		this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false));
      		this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true));
      
      		// The JDK does not contain default editors for number wrapper types!
      		// Override JDK primitive number editors with our own CustomNumberEditor.
      		this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false));
      		this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
      		this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false));
      		this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
      		this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false));
      		this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
      		this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false));
      		this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
      		this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false));
      		this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
      		this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false));
      		this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
      		this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
      		this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));
      
      		// Only register config value editors if explicitly requested.
          	// 仅在明确要求时注册配置值编辑器
      		if (this.configValueEditorsActive) {
      			StringArrayPropertyEditor sae = new StringArrayPropertyEditor();
      			this.defaultEditors.put(String[].class, sae);
      			this.defaultEditors.put(short[].class, sae);
      			this.defaultEditors.put(int[].class, sae);
      			this.defaultEditors.put(long[].class, sae);
      		}
      	}
      
      /**
       * 把这个注册表实例中的默认编辑器复制到另一个注册表中
       * @param target the target registry to copy to
       */
      protected void copyDefaultEditorsTo(PropertyEditorRegistrySupport target) {
          target.defaultEditorsActive = this.defaultEditorsActive;
          target.configValueEditorsActive = this.configValueEditorsActive;
          target.defaultEditors = this.defaultEditors;
          target.overriddenDefaultEditors = this.overriddenDefaultEditors;
      }
      
    • 关于自定义编辑器的方法

      • 实现的PropertyEditorRegistry接口中的三个方法
      @Override
      public void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
         registerCustomEditor(requiredType, null, propertyEditor);
      }
      
      @Override
      public void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor) {
         if (requiredType == null && propertyPath == null) {
            throw new IllegalArgumentException("Either requiredType or propertyPath is required");
         }
         if (propertyPath != null) {
            if (this.customEditorsForPath == null) {
               this.customEditorsForPath = new LinkedHashMap<>(16);
            }
            this.customEditorsForPath.put(propertyPath, new CustomEditorHolder(propertyEditor, requiredType));
         }
         else {
            if (this.customEditors == null) {
               this.customEditors = new LinkedHashMap<>(16);
            }
            this.customEditors.put(requiredType, propertyEditor);
            this.customEditorCache = null;
         }
      }
      
      @Override
      @Nullable
      public PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath) {
         Class<?> requiredTypeToUse = requiredType;
         if (propertyPath != null) {
            if (this.customEditorsForPath != null) {
               // Check property-specific editor first.
               PropertyEditor editor = getCustomEditor(propertyPath, requiredType);
               if (editor == null) {
                  List<String> strippedPaths = new ArrayList<>();
                  addStrippedPropertyPaths(strippedPaths, "", propertyPath);
                  for (Iterator<String> it = strippedPaths.iterator(); it.hasNext() && editor == null;) {
                     String strippedPath = it.next();
                     editor = getCustomEditor(strippedPath, requiredType);
                  }
               }
               if (editor != null) {
                  return editor;
               }
            }
            if (requiredType == null) {
               requiredTypeToUse = getPropertyType(propertyPath);
            }
         }
         // No property-specific editor -> check type-specific editor.
         return getCustomEditor(requiredTypeToUse);
      }
      
      //这个注册表是否含有特定 array/Collection 元素类 的自定义编辑器
      public boolean hasCustomEditorForElement(@Nullable Class<?> elementType, @Nullable String propertyPath) {
      		if (propertyPath != null && this.customEditorsForPath != null) {
      			for (Map.Entry<String, CustomEditorHolder> entry : this.customEditorsForPath.entrySet()) {
      				if (PropertyAccessorUtils.matchesProperty(entry.getKey(), propertyPath) &&
      						entry.getValue().getPropertyEditor(elementType) != null) {
      					return true;
      				}
      			}
      		}
      		// No property-specific editor -> check type-specific editor.
      		return (elementType != null && this.customEditors != null && this.customEditors.containsKey(elementType));
      }
      
      //根据property path得到该属性的类型,默认返回null,该方法在BeanWrapper中被再次定义,且在BeanWrapperImpl中被重写
      @Nullable
      protected Class<?> getPropertyType(String propertyPath) {
          return null;
      }
      
      //返回指定类型和属性的自定义编辑器
      @Nullable
      private PropertyEditor getCustomEditor(String propertyName, @Nullable Class<?> requiredType) {
          CustomEditorHolder holder =
                  (this.customEditorsForPath != null ? this.customEditorsForPath.get(propertyName) : null);
          return (holder != null ? holder.getPropertyEditor(requiredType) : null);
      }
      
      //返回指定type的自定义编辑器,如果没有直接匹配的结果,将会尝试其父类的自定义编辑器(在任何情况下都能通过 getAsText将值呈现为String)
      @Nullable
      private PropertyEditor getCustomEditor(@Nullable Class<?> requiredType) {
          if (requiredType == null || this.customEditors == null) {
              return null;
          }
          // Check directly registered editor for type.
          PropertyEditor editor = this.customEditors.get(requiredType);
          if (editor == null) {
              // Check cached editor for type, registered for superclass or interface.
              if (this.customEditorCache != null) {
                  editor = this.customEditorCache.get(requiredType);
              }
              if (editor == null) {
                  // Find editor for superclass or interface.
                  for (Iterator<Class<?>> it = this.customEditors.keySet().iterator(); it.hasNext() && editor == null;) {
                      Class<?> key = it.next();
                      if (key.isAssignableFrom(requiredType)) {
                          editor = this.customEditors.get(key);
                          // Cache editor for search type, to avoid the overhead
                          // of repeated assignable-from checks.
                          if (this.customEditorCache == null) {
                              this.customEditorCache = new HashMap<>();
                          }
                          this.customEditorCache.put(requiredType, editor);
                      }
                  }
              }
          }
          return editor;
      }
      
      //猜猜该属性名称所对应的属性类型(从自定义编辑器中猜)
      @Nullable
      protected Class<?> guessPropertyTypeFromEditors(String propertyName) {
          if (this.customEditorsForPath != null) {
              CustomEditorHolder editorHolder = this.customEditorsForPath.get(propertyName);
              if (editorHolder == null) {
                  List<String> strippedPaths = new ArrayList<>();
                  addStrippedPropertyPaths(strippedPaths, "", propertyName);
                  for (Iterator<String> it = strippedPaths.iterator(); it.hasNext() && editorHolder == null;) {
                      String strippedName = it.next();
                      editorHolder = this.customEditorsForPath.get(strippedName);
                  }
              }
              if (editorHolder != null) {
                  return editorHolder.getRegisteredType();
              }
          }
          return null;
      }
      
      /**把这个注册表实例中的自定义编辑器复制到目标注册表实例中
       */
      protected void copyCustomEditorsTo(PropertyEditorRegistry target, @Nullable String nestedProperty) {
          String actualPropertyName =
                  (nestedProperty != null ? PropertyAccessorUtils.getPropertyName(nestedProperty) : null);
          if (this.customEditors != null) {
              this.customEditors.forEach(target::registerCustomEditor);
          }
          if (this.customEditorsForPath != null) {
              this.customEditorsForPath.forEach((editorPath, editorHolder) -> {
                  if (nestedProperty != null) {
                      int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(editorPath);
                      if (pos != -1) {
                          String editorNestedProperty = editorPath.substring(0, pos);
                          String editorNestedPath = editorPath.substring(pos + 1);
                          if (editorNestedProperty.equals(nestedProperty) || editorNestedProperty.equals(actualPropertyName)) {
                              target.registerCustomEditor(
                                      editorHolder.getRegisteredType(), editorNestedPath, editorHolder.getPropertyEditor());
                          }
                      }
                  }
                  else {
                      target.registerCustomEditor(
                              editorHolder.getRegisteredType(), editorPath, editorHolder.getPropertyEditor());
                  }
              });
          }
      }
      
      
      /**添加具有剥离键和/或索引的所有变体的属性路径。使用嵌套路径递归调用自身。*/
      private void addStrippedPropertyPaths(List<String> strippedPaths, String nestedPath, String propertyPath) {
          int startIndex = propertyPath.indexOf(PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR);
          if (startIndex != -1) {
              int endIndex = propertyPath.indexOf(PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR);
              if (endIndex != -1) {
                  String prefix = propertyPath.substring(0, startIndex);
                  String key = propertyPath.substring(startIndex, endIndex + 1);
                  String suffix = propertyPath.substring(endIndex + 1, propertyPath.length());
                  // Strip the first key.
                  strippedPaths.add(nestedPath + prefix + suffix);
                  // Search for further keys to strip, with the first key stripped.
                  addStrippedPropertyPaths(strippedPaths, nestedPath + prefix, suffix);
                  // Search for further keys to strip, with the first key not stripped.
                  addStrippedPropertyPaths(strippedPaths, nestedPath + prefix + key, suffix);
              }
          }
      }
      
    • 内部类CustomEditorHolder

      //具有属性名称的注册定制编辑器的持有人。
      //保留PropertyEditor本身及其注册的类型。
      private static final class CustomEditorHolder {
      
          private final PropertyEditor propertyEditor;
      
          @Nullable
          private final Class<?> registeredType;
      
          private CustomEditorHolder(PropertyEditor propertyEditor, @Nullable Class<?> registeredType) {
              this.propertyEditor = propertyEditor;
              this.registeredType = registeredType;
          }
      
          private PropertyEditor getPropertyEditor() {
              return this.propertyEditor;
          }
      
          @Nullable
          private Class<?> getRegisteredType() {
              return this.registeredType;
          }
      
          @Nullable
          private PropertyEditor getPropertyEditor(@Nullable Class<?> requiredType) {
              // 特殊情况:如果没有指定的requiredType(通常只发生在是Collection元素的时候),或者requiredType没有被分派到注册表中的类型(通常只发生在Object的通用属性的情况),那么就会返回PropertyEditor(没有注册为Collection和array type)
              if (this.registeredType == null ||
                      (requiredType != null &&
                      (ClassUtils.isAssignable(this.registeredType, requiredType) ||
                      ClassUtils.isAssignable(requiredType, this.registeredType))) ||
                      (requiredType == null &&
                      (!Collection.class.isAssignableFrom(this.registeredType) && !this.registeredType.isArray()))) {
                  return this.propertyEditor;
              }
              else {
                  return null;
              }
          }
      }
      
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!