Removed support for deprecated registerSharedEditor mechanism

This commit is contained in:
Juergen Hoeller 2013-05-03 11:49:53 +02:00
parent 0a8f5b2919
commit 61c3f3d9fd
4 changed files with 19 additions and 244 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,7 +27,6 @@ import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Currency;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
@ -99,8 +98,6 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
private Map<String, CustomEditorHolder> customEditorsForPath;
private Set<PropertyEditor> sharedEditors;
private Map<Class<?>, PropertyEditor> customEditorCache;
@ -292,33 +289,6 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
}
}
/**
* Register the given custom property editor for all properties
* of the given type, indicating that the given instance is a
* shared editor that might be used concurrently.
* @param requiredType the type of the property
* @param propertyEditor the shared editor to register
* @deprecated as of Spring 3.0, in favor of PropertyEditorRegistrars or ConversionService usage
*/
@Deprecated
public void registerSharedEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
registerCustomEditor(requiredType, null, propertyEditor);
if (this.sharedEditors == null) {
this.sharedEditors = new HashSet<PropertyEditor>();
}
this.sharedEditors.add(propertyEditor);
}
/**
* Check whether the given editor instance is a shared editor, that is,
* whether the given editor instance might be used concurrently.
* @param propertyEditor the editor instance to check
* @return whether the editor is a shared instance
*/
public boolean isSharedEditor(PropertyEditor propertyEditor) {
return (this.sharedEditors != null && this.sharedEditors.contains(propertyEditor));
}
public PropertyEditor findCustomEditor(Class<?> requiredType, String propertyPath) {
Class<?> requiredTypeToUse = requiredType;
if (propertyPath != null) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -354,11 +354,6 @@ class TypeConverterDelegate {
*/
private Object doConvertValue(Object oldValue, Object newValue, Class<?> requiredType, PropertyEditor editor) {
Object convertedValue = newValue;
boolean sharedEditor = false;
if (editor != null) {
sharedEditor = this.propertyEditorRegistry.isSharedEditor(editor);
}
if (editor != null && !(convertedValue instanceof String)) {
// Not a String -> use PropertyEditor's setValue.
@ -366,19 +361,8 @@ class TypeConverterDelegate {
// we just want to allow special PropertyEditors to override setValue
// for type conversion from non-String values to the required type.
try {
Object newConvertedValue;
if (sharedEditor) {
// Synchronized access to shared editor instance.
synchronized (editor) {
editor.setValue(convertedValue);
newConvertedValue = editor.getValue();
}
}
else {
// Unsynchronized access to non-shared editor instance.
editor.setValue(convertedValue);
newConvertedValue = editor.getValue();
}
editor.setValue(convertedValue);
Object newConvertedValue = editor.getValue();
if (newConvertedValue != convertedValue) {
convertedValue = newConvertedValue;
// Reset PropertyEditor: It already did a proper conversion.
@ -413,16 +397,7 @@ class TypeConverterDelegate {
logger.trace("Converting String to [" + requiredType + "] using property editor [" + editor + "]");
}
String newTextValue = (String) convertedValue;
if (sharedEditor) {
// Synchronized access to shared editor instance.
synchronized (editor) {
return doConvertTextValue(oldValue, newTextValue, editor);
}
}
else {
// Unsynchronized access to non-shared editor instance.
return doConvertTextValue(oldValue, newTextValue, editor);
}
return doConvertTextValue(oldValue, newTextValue, editor);
}
else if (String.class.equals(requiredType)) {
returnValue = convertedValue;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,22 +23,16 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyEditorRegistrySupport;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link BeanFactoryPostProcessor} implementation that allows for convenient
* registration of custom {@link PropertyEditor property editors}.
*
* <p>
* In case you want to register {@link PropertyEditor} instances, the
* recommended usage as of Spring 2.0 is to use custom
* <p>In case you want to register {@link PropertyEditor} instances,
* the recommended usage as of Spring 2.0 is to use custom
* {@link PropertyEditorRegistrar} implementations that in turn register any
* desired editor instances on a given
* {@link org.springframework.beans.PropertyEditorRegistry registry}. Each
@ -100,7 +94,7 @@ import org.springframework.util.ClassUtils;
* @see org.springframework.web.servlet.mvc.BaseCommandController#setPropertyEditorRegistrars
* @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder
*/
public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanClassLoaderAware, Ordered {
public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered {
protected final Log logger = LogFactory.getLog(getClass());
@ -108,11 +102,7 @@ public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanCla
private PropertyEditorRegistrar[] propertyEditorRegistrars;
private Map<String, ?> customEditors;
private boolean ignoreUnresolvableEditors = false;
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private Map<Class<?>, Class<? extends PropertyEditor>> customEditors;
public void setOrder(int order) {
@ -141,30 +131,12 @@ public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanCla
* Specify the custom editors to register via a {@link Map}, using the
* class name of the required type as the key and the class name of the
* associated {@link PropertyEditor} as value.
* <p>Also supports {@link PropertyEditor} instances as values; however,
* this is deprecated since Spring 2.0.7!
* @see ConfigurableListableBeanFactory#registerCustomEditor
*/
public void setCustomEditors(Map<String, ?> customEditors) {
public void setCustomEditors(Map<Class<?>, Class<? extends PropertyEditor>> customEditors) {
this.customEditors = customEditors;
}
/**
* Set whether unresolvable editors should simply be skipped.
* Default is to raise an exception in such a case.
* <p>This typically applies to either the editor class or the required type
* class not being found in the classpath. If you expect this to happen in
* some deployments and prefer to simply ignore the affected editors,
* then switch this flag to "true".
*/
public void setIgnoreUnresolvableEditors(boolean ignoreUnresolvableEditors) {
this.ignoreUnresolvableEditors = ignoreUnresolvableEditors;
}
public void setBeanClassLoader(ClassLoader beanClassLoader) {
this.beanClassLoader = beanClassLoader;
}
@SuppressWarnings("unchecked")
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
@ -173,77 +145,13 @@ public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanCla
beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
}
}
if (this.customEditors != null) {
for (Map.Entry<String, ?> entry : this.customEditors.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
Class requiredType = null;
try {
requiredType = ClassUtils.forName(key, this.beanClassLoader);
if (value instanceof PropertyEditor) {
if (logger.isWarnEnabled()) {
logger.warn("Passing PropertyEditor instances into CustomEditorConfigurer is deprecated: " +
"use PropertyEditorRegistrars or PropertyEditor class names instead. " +
"Offending key [" + key + "; offending editor instance: " + value);
}
beanFactory.addPropertyEditorRegistrar(
new SharedPropertyEditorRegistrar(requiredType, (PropertyEditor) value));
}
else if (value instanceof Class) {
beanFactory.registerCustomEditor(requiredType, (Class) value);
}
else if (value instanceof String) {
Class editorClass = ClassUtils.forName((String) value, this.beanClassLoader);
Assert.isAssignable(PropertyEditor.class, editorClass);
beanFactory.registerCustomEditor(requiredType, editorClass);
}
else {
throw new IllegalArgumentException("Mapped value [" + value + "] for custom editor key [" +
key + "] is not of required type [" + PropertyEditor.class.getName() +
"] or a corresponding Class or String value indicating a PropertyEditor implementation");
}
}
catch (ClassNotFoundException ex) {
if (this.ignoreUnresolvableEditors) {
logger.info("Skipping editor [" + value + "] for required type [" + key + "]: " +
(requiredType != null ? "editor" : "required type") + " class not found.");
}
else {
throw new FatalBeanException(
(requiredType != null ? "Editor" : "Required type") + " class not found", ex);
}
}
for (Map.Entry<Class<?>, Class<? extends PropertyEditor>> entry : this.customEditors.entrySet()) {
Class requiredType = entry.getKey();
Class<? extends PropertyEditor> propertyEditorClass = entry.getValue();
beanFactory.registerCustomEditor(requiredType, propertyEditorClass);
}
}
}
/**
* PropertyEditorRegistrar that registers a (deprecated) shared editor.
*/
private static class SharedPropertyEditorRegistrar implements PropertyEditorRegistrar {
private final Class requiredType;
private final PropertyEditor sharedEditor;
public SharedPropertyEditorRegistrar(Class requiredType, PropertyEditor sharedEditor) {
this.requiredType = requiredType;
this.sharedEditor = sharedEditor;
}
@Override
@SuppressWarnings("deprecation")
public void registerCustomEditors(PropertyEditorRegistry registry) {
if (!(registry instanceof PropertyEditorRegistrySupport)) {
throw new IllegalArgumentException("Cannot registered shared editor " +
"on non-PropertyEditorRegistrySupport registry: " + registry);
}
((PropertyEditorRegistrySupport) registry).registerSharedEditor(this.requiredType, this.sharedEditor);
}
}
}

View File

@ -38,8 +38,6 @@ import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.tests.sample.beans.TestBean;
/**
* Unit tests for {@link CustomEditorConfigurer}.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 31.07.2004
@ -77,59 +75,12 @@ public final class CustomEditorConfigurerTests {
assertEquals(df.parse("2.12.1975"), tb2.getSomeMap().get("myKey"));
}
@Test
public void testCustomEditorConfigurerWithEditorInstance() throws ParseException {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
CustomEditorConfigurer cec = new CustomEditorConfigurer();
Map<String, PropertyEditor> editors = new HashMap<String, PropertyEditor>();
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
editors.put(Date.class.getName(), new CustomDateEditor(df, true));
cec.setCustomEditors(editors);
cec.postProcessBeanFactory(bf);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("date", "2.12.1975");
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
bd1.setPropertyValues(pvs);
bf.registerBeanDefinition("tb1", bd1);
pvs = new MutablePropertyValues();
pvs.add("someMap[myKey]", new TypedStringValue("2.12.1975", Date.class));
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
bd2.setPropertyValues(pvs);
bf.registerBeanDefinition("tb2", bd2);
TestBean tb1 = (TestBean) bf.getBean("tb1");
assertEquals(df.parse("2.12.1975"), tb1.getDate());
TestBean tb2 = (TestBean) bf.getBean("tb2");
assertEquals(df.parse("2.12.1975"), tb2.getSomeMap().get("myKey"));
}
@Test
public void testCustomEditorConfigurerWithEditorClassName() throws ParseException {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
CustomEditorConfigurer cec = new CustomEditorConfigurer();
Map<String, String> editors = new HashMap<String, String>();
editors.put(Date.class.getName(), MyDateEditor.class.getName());
cec.setCustomEditors(editors);
cec.postProcessBeanFactory(bf);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("date", "2.12.1975");
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
bd.setPropertyValues(pvs);
bf.registerBeanDefinition("tb", bd);
TestBean tb = (TestBean) bf.getBean("tb");
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
assertEquals(df.parse("2.12.1975"), tb.getDate());
}
@Test
public void testCustomEditorConfigurerWithEditorAsClass() throws ParseException {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
CustomEditorConfigurer cec = new CustomEditorConfigurer();
Map<String, Class> editors = new HashMap<String, Class>();
editors.put(Date.class.getName(), MyDateEditor.class);
Map<Class<?>, Class<? extends PropertyEditor>> editors = new HashMap<Class<?>, Class<? extends PropertyEditor>>();
editors.put(Date.class, MyDateEditor.class);
cec.setCustomEditors(editors);
cec.postProcessBeanFactory(bf);
@ -148,8 +99,8 @@ public final class CustomEditorConfigurerTests {
public void testCustomEditorConfigurerWithRequiredTypeArray() throws ParseException {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
CustomEditorConfigurer cec = new CustomEditorConfigurer();
Map<String, String> editors = new HashMap<String, String>();
editors.put("java.lang.String[]", MyTestEditor.class.getName());
Map<Class<?>, Class<? extends PropertyEditor>> editors = new HashMap<Class<?>, Class<? extends PropertyEditor>>();
editors.put(String[].class, MyTestEditor.class);
cec.setCustomEditors(editors);
cec.postProcessBeanFactory(bf);
@ -164,35 +115,6 @@ public final class CustomEditorConfigurerTests {
assertEquals("test", tb.getStringArray()[0]);
}
@Test
public void testCustomEditorConfigurerWithUnresolvableEditor() throws ParseException {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
CustomEditorConfigurer cec = new CustomEditorConfigurer();
Map<String, String> editors = new HashMap<String, String>();
editors.put(Date.class.getName(), "MyNonExistingEditor");
editors.put("MyNonExistingType", "MyNonExistingEditor");
cec.setCustomEditors(editors);
try {
cec.postProcessBeanFactory(bf);
fail("Should have thrown FatalBeanException");
}
catch (FatalBeanException ex) {
assertTrue(ex.getCause() instanceof ClassNotFoundException);
}
}
@Test
public void testCustomEditorConfigurerWithIgnoredUnresolvableEditor() throws ParseException {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
CustomEditorConfigurer cec = new CustomEditorConfigurer();
Map<String, String> editors = new HashMap<String, String>();
editors.put(Date.class.getName(), "MyNonExistingEditor");
editors.put("MyNonExistingType", "MyNonExistingEditor");
cec.setCustomEditors(editors);
cec.setIgnoreUnresolvableEditors(true);
cec.postProcessBeanFactory(bf);
}
public static class MyDateEditor extends CustomDateEditor {