探秘Spring的PropertyEditor

中国人最喜欢访问的网站
只要注册ofo就送你10块钱,还等什么,快来注册吧

java.beans.PropertyEditor是JDK自带的类,是提供给AWT。

Spring利用该接口来实现Bean的属性转换器。

Spring xml配置的bean属性都是字符串类型的值,但是对应到的每个具体的属性是各种类型的,Spring通过各种PropertyEditor来对各个属性进行类型转换。

Spring并不是直接实现PropertyEditor接口,而是继承PropertyEditorSupport类。

PropertyEditorRegistry

BeanWrapperImplPropertyEditorRegistrySupport的子类。
PropertyEditorRegistry是一个接口,PropertyEditorRegistrySupport是它的实现类。
PropertyEditorRegistrySupport中的方法createDefaultEditors,该方法初始化Spring中默认PropertyEditor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
* Actually register the default editors for this registry instance.
*/
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);
}
}

可能上面能够转换的类型还不能满足需求,那么可以通过另一种方式将PropertyEditor注入到Spring中。

PropertyEditorRegistrar

该接口只有一个方法:

1
void registerCustomEditors(PropertyEditorRegistry registry)

实现该方法就可以往传入的registry添加自定义的PropertyEditor,一般情况下传入的registry是BeanWrapperImpl的实例,即将自定义的PropertyEditor注入到BeanWrapperImpl

CustomEditorConfigurer

1
2
3
4
5
6
7
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.propertyEditorRegistrars != null) {
for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
}
}
}

PropertyEditorRegistrar添加到BeanFactory

它是实现了BeanFactoryPostProcessor接口,即在构造完BeanDefinition之后会调用方法postProcessBeanFactory

注入一个CustomEditorConfigurerBean(设置propertyEditorRegistrarscustomEditors属性)就可以将自定义的PropertyEditor注入到Spring中了。

例子

自定义PropertyEditor

1
2
3
4
5
6
7
8
9
10
11
12
public class CustomPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
super.setAsText(text);
}
@Override
public Object getValue() {
return super.getValue();
}
}

将这个PropertyEditor注入到Spring里面中

1
2
3
4
5
6
7
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.xx.foo.FooPojo" value="com.xx.foo.CustomPropertyEditor"/>
</map>
</property>
</bean>

ClassEditor的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class ClassEditor extends PropertyEditorSupport {
private final ClassLoader classLoader;
public ClassEditor() {
this(null);
}
public ClassEditor(ClassLoader classLoader) {
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
setValue(ClassUtils.resolveClassName(text.trim(), this.classLoader));
}
else {
setValue(null);
}
}
@Override
public String getAsText() {
Class clazz = (Class) getValue();
if (clazz != null) {
return ClassUtils.getQualifiedName(clazz);
}
else {
return "";
}
}
}
快下载安装吧,今天头条送你钱啦!!!!
中国人都在使用的地球上最好玩的游戏
中国人都在使用的地球上最好玩的游戏
中国人都在使用的地球上最快的浏览器
中国人都在使用的地球上最厉害的安全软件
中国人都在使用的地球上最好的看图王
中国人都在使用的地球上最快速的视频软件
中国人都在使用的地球上最全的视频软件
中国人都在使用的地球上最好最全的压缩软件
中国人都在使用的地球上最好的音乐播放器
中国人都在使用的地球上最安全的杀毒软件
中国人都在使用的地球上最全的影视大全