- 介绍
- 使用
- 使用默认属性编辑器
- 源码浅述
- 使用例子
- 注册自定义属性编辑器
PropertyEditorRegistrySupport
类实现了PropertyEditorRegistry
接口。
其维护的是一系列java.beans
包下的PropertyEditor
;提供对默认属性编辑器和自定义属性编辑器的管理;该类主要作为BeanWrapperImpl
基类。
其继承主要的继承关系如下图:
从类图来看,BeanWrapperImpl
继承了PropertyEditorRegistrySupport
类,所以学习BeanWrapperImpl
的过程中,是有必要弄明白PropertyEditorRegistrySupport
是个什么类,并且知道它是怎么玩的。
PropertyEditorRegistrySupport
提供了如下方法:
方法 | 描述 |
---|---|
void setConversionService(@Nullable ConversionService conversionService) | 指定一个ConversionService 用于转换属性值,作为JavaBeans 的PropertyEditors 的替代方法。 |
ConversionService getConversionService() | 获取ConversionService 。 |
void registerDefaultEditors() | 将defaultEditorsActive 属性设置为true ;标记该类注册默认的属性编辑器,可以通过getDefaultEditor(requiredType) 方法来获取默认的属性编辑器。 |
void useConfigValueEditors() | 将configValueEditorsActive 属性设置为true ;标记该类注册默认StringArrayPropertyEdito ,其可以将字符串按照特定分隔符分割转换成数组。 |
void overrideDefaultEditor(Class> requiredType, PropertyEditor propertyEditor) | 使用传入的propertyEditor 覆盖requiredType 类型的默认编辑器。这与注册自定义编辑器不同,因为该编辑器仍然是默认编辑器。 ConversionService 将覆盖这样的默认编辑器,而自定义编辑器通常会覆盖ConversionService 。 |
PropertyEditor getDefaultEditor(Class> requiredType) | 根据指定类型获取其对应的默认属性编辑器。 |
void registerCustomEditor(Class> requiredType, PropertyEditor propertyEditor) | 注册指定类型的自定义属性编辑器。 |
void registerCustomEditor(@Nullable Class> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor) | 注册指定类型指定属性名的自定义属性编辑器。如果指定了propertyPath 属性,并且没有额外注册requiredType 对应的自定义属性编辑器,那么调用findCustomEditor() 方法时就必须传入propertyPath |
PropertyEditor findCustomEditor(@Nullable Class> requiredType, @Nullable String propertyPath) | 根据类型和属性名来查找属性编辑器; |
boolean hasCustomEditorForElement(@Nullable Class> elementType, @Nullable String propertyPath) | 判断是否包含elementType 类型对应的propertyPath 属性值的属性编辑器。 |
如果要使用默认编辑器,我们需要通过getDefaultEditor(Class requiredType)
方法来获取默认注册的属性编辑器,所以我们看该方法的源码:
从上面的源码可以看出,如果我们需要使用默认属性编辑器还需要将defaultEditorsActive
属性设置成true
,否则直接返回null
。
另外如果调用了overrideDefaultEditor()
方法注册了覆盖特定类型的属性编辑器,则会优先从overriddenDefaultEditors
中获取,如果overriddenDefaultEditors
没有获取到,就会从defaultEditors
集合中获取,defaultEditors
在第一次调用getDefaultEditor()
的时候进行创建加载。
接下来进入到createDefaultEditors();
中看下:
org.springframework.beans.PropertyEditorRegistrySupport#createDefaultEditors
private void createDefaultEditors() {
this.defaultEditors = new HashMap<>(64);
// Simple editors, without parameterization capabilities.
// 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());
// Default instances of collection editors.
// 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));
// Default editors for primitive arrays.
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);
}
}
如果开启了默认属性编辑器(defaultEditorsActive
设置成了true
),那么会调用上面的createDefaultEditors()
方法,在该方法中,如上所看到的,会向defaultEditors
集合中注册一系列类型的属性编辑器。
使用例子
如果要使用PropertyEditorRegistrySupport
的默认属性编辑器,需要将defaultEditorsActive
属性设置成true
。
但由于registerDefaultEditors()
方法是protected
权限:
所以本例子,我们通过反射来进行更改此属性。
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
PropertyEditorRegistrySupport registrySupport = new PropertyEditorRegistrySupport();
// 将defaultEditorsActive设置成true,来使用默认编辑器
Field defaultEditorsActive = PropertyEditorRegistrySupport.class.getDeclaredField("defaultEditorsActive");
defaultEditorsActive.setAccessible(true);
defaultEditorsActive.set(registrySupport, true);
//使用值配置编辑器(String[]、short[]、int[]、long[])类型的转换
registrySupport.useConfigValueEditors();
//bool类型属性编辑器
System.out.println("-------------默认boolean属性编辑器------------");
PropertyEditor booleanEditor = registrySupport.getDefaultEditor(boolean.class);
booleanEditor.setAsText("true");
System.out.println("true->" + booleanEditor.getAsText());
booleanEditor.setAsText("True");
System.out.println("True->" + booleanEditor.getAsText());
booleanEditor.setAsText("yes");
System.out.println("yes->" + booleanEditor.getAsText());
booleanEditor.setAsText("on");
System.out.println("on->" + booleanEditor.getAsText());
booleanEditor.setAsText("1");
System.out.println("1->" + booleanEditor.getAsText());
booleanEditor.setAsText("false");
System.out.println("false->" + booleanEditor.getAsText());
booleanEditor.setAsText("False");
System.out.println("False->" + booleanEditor.getAsText());
booleanEditor.setAsText("no");
System.out.println("no->" + booleanEditor.getAsText());
booleanEditor.setAsText("off");
System.out.println("off->" + booleanEditor.getAsText());
booleanEditor.setAsText("0");
System.out.println("0->" + booleanEditor.getAsText());
System.out.println("-------------字符串转数组(\"苹果,香蕉,橘子\")------------");
registrySupport.getDefaultEditor(String[].class).setAsText("苹果,香蕉,橘子");
String[] fruits = (String[]) registrySupport.getDefaultEditor(String[].class).getValue();
for (int i = 0; i < fruits.length; i++) {
System.out.println(i + ":" + fruits[i]);
}
}
输出结果:
注册自定义属性编辑器
除了PropertyEditorRegistrySupport
给我们提供了默认常用类型的属性编辑器之外,我们还可以给特定类型自定义属性编辑器。
本例子中,我们有一个Address
类,其中有省\市\区三个字段;我们还有一个用于将形如"湖南省|长沙市|望城区"的字符串转换成Address
类对象的自定义属性编辑器:AddressPropertyEditor
package com.baiyang.bean;
public class Address {
private String province;
private String city;
private String district;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
", district='" + district + '\'' +
'}';
}
}
package com.baiyang.bean;
import org.springframework.util.StringUtils;
import java.beans.PropertyEditorSupport;
/**
* User: Yang Peng
* DateTime:2022/5/13 16:26
*/
public class AddressPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.isEmpty(text)) {
return;
}
String[] arrs = text.split("\|");
Address address = new Address();
if (arrs.length >= 1) {
address.setProvince(arrs[0]);//省
}
if (arrs.length >= 2) {
address.setCity(arrs[1]);//市
}
if (arrs.length > 2) {
address.setDistrict(arrs[2]);//区
}
setValue(address);
}
}
接下来我们通过下面的代码来注册我们自定义的AddressPropertyEditor
并转换测试:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
PropertyEditorRegistrySupport registrySupport = new PropertyEditorRegistrySupport();
// 将defaultEditorsActive设置成true,来使用默认编辑器
Field defaultEditorsActive = PropertyEditorRegistrySupport.class.getDeclaredField("defaultEditorsActive");
defaultEditorsActive.setAccessible(true);
defaultEditorsActive.set(registrySupport, true);
//使用值配置编辑器(String[]、short[]、int[]、long[])类型的转换
registrySupport.useConfigValueEditors();
registrySupport.registerCustomEditor(Address.class, new AddressPropertyEditor());
PropertyEditor addressEditor = registrySupport.findCustomEditor(Address.class, null);
System.out.println("-------湖南省------");
addressEditor.setAsText("湖南省");
System.out.println(addressEditor.getAsText());
System.out.println("-------湖南省|长沙市------");
addressEditor.setAsText("湖南省|长沙市");
System.out.println(addressEditor.getAsText());
System.out.println("-------湖南省|长沙市|望城区------");
addressEditor.setAsText("湖南省|长沙市|望城区");
System.out.println(addressEditor.getAsText());
}
输出结果:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)