/*
 * Copyright 2002-2018 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import java.beans.PropertyEditor;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

BeanFactoryPostProcessor implementation that allows for convenient registration of custom property editors.

In case you want to register PropertyEditor instances, the recommended usage as of Spring 2.0 is to use custom PropertyEditorRegistrar implementations that in turn register any desired editor instances on a given registry. Each PropertyEditorRegistrar can register any number of custom editors.

<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="propertyEditorRegistrars">
    <list>
      <bean class="mypackage.MyCustomDateEditorRegistrar"/>
      <bean class="mypackage.MyObjectEditorRegistrar"/>
    </list>
  </property>
</bean>

It's perfectly fine to register PropertyEditor classes via the customEditors property. Spring will create fresh instances of them for each editing attempt then:

<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="customEditors">
    <map>
      <entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/>
      <entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/>
    </map>
  </property>
</bean>

Note, that you shouldn't register PropertyEditor bean instances via the customEditors property as PropertyEditors are stateful and the instances will then have to be synchronized for every editing attempt. In case you need control over the instantiation process of PropertyEditors, use a PropertyEditorRegistrar to register them.

Also supports "java.lang.String[]"-style array class names and primitive class names (e.g. "boolean"). Delegates to ClassUtils for actual class name resolution.

NOTE: Custom property editors registered with this configurer do not apply to data binding. Custom editors for data binding need to be registered on the DataBinder: Use a common base class or delegate to common PropertyEditorRegistrar implementations to reuse editor registration there.

Author:Juergen Hoeller
See Also:
Since:27.02.2004
/** * {@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 * {@link PropertyEditorRegistrar} implementations that in turn register any * desired editor instances on a given * {@link org.springframework.beans.PropertyEditorRegistry registry}. Each * PropertyEditorRegistrar can register any number of custom editors. * * <pre class="code"> * &lt;bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt; * &lt;property name="propertyEditorRegistrars"&gt; * &lt;list&gt; * &lt;bean class="mypackage.MyCustomDateEditorRegistrar"/&gt; * &lt;bean class="mypackage.MyObjectEditorRegistrar"/&gt; * &lt;/list&gt; * &lt;/property&gt; * &lt;/bean&gt; * </pre> * * <p> * It's perfectly fine to register {@link PropertyEditor} <em>classes</em> via * the {@code customEditors} property. Spring will create fresh instances of * them for each editing attempt then: * * <pre class="code"> * &lt;bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt; * &lt;property name="customEditors"&gt; * &lt;map&gt; * &lt;entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/&gt; * &lt;entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/&gt; * &lt;/map&gt; * &lt;/property&gt; * &lt;/bean&gt; * </pre> * * <p> * Note, that you shouldn't register {@link PropertyEditor} bean instances via * the {@code customEditors} property as {@link PropertyEditor PropertyEditors} are stateful * and the instances will then have to be synchronized for every editing * attempt. In case you need control over the instantiation process of * {@link PropertyEditor PropertyEditors}, use a {@link PropertyEditorRegistrar} to register * them. * * <p> * Also supports "java.lang.String[]"-style array class names and primitive * class names (e.g. "boolean"). Delegates to {@link ClassUtils} for actual * class name resolution. * * <p><b>NOTE:</b> Custom property editors registered with this configurer do * <i>not</i> apply to data binding. Custom editors for data binding need to * be registered on the {@link org.springframework.validation.DataBinder}: * Use a common base class or delegate to common PropertyEditorRegistrar * implementations to reuse editor registration there. * * @author Juergen Hoeller * @since 27.02.2004 * @see java.beans.PropertyEditor * @see org.springframework.beans.PropertyEditorRegistrar * @see ConfigurableBeanFactory#addPropertyEditorRegistrar * @see ConfigurableBeanFactory#registerCustomEditor * @see org.springframework.validation.DataBinder#registerCustomEditor */
public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered { protected final Log logger = LogFactory.getLog(getClass()); private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered @Nullable private PropertyEditorRegistrar[] propertyEditorRegistrars; @Nullable private Map<Class<?>, Class<? extends PropertyEditor>> customEditors; public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return this.order; }
Specify the PropertyEditorRegistrars to apply to beans defined within the current application context.

This allows for sharing PropertyEditorRegistrars with DataBinders, etc. Furthermore, it avoids the need for synchronization on custom editors: A PropertyEditorRegistrar will always create fresh editor instances for each bean creation attempt.

See Also:
/** * Specify the {@link PropertyEditorRegistrar PropertyEditorRegistrars} * to apply to beans defined within the current application context. * <p>This allows for sharing {@code PropertyEditorRegistrars} with * {@link org.springframework.validation.DataBinder DataBinders}, etc. * Furthermore, it avoids the need for synchronization on custom editors: * A {@code PropertyEditorRegistrar} will always create fresh editor * instances for each bean creation attempt. * @see ConfigurableListableBeanFactory#addPropertyEditorRegistrar */
public void setPropertyEditorRegistrars(PropertyEditorRegistrar[] propertyEditorRegistrars) { this.propertyEditorRegistrars = propertyEditorRegistrars; }
Specify the custom editors to register via a Map, using the class name of the required type as the key and the class name of the associated PropertyEditor as value.
See Also:
/** * 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. * @see ConfigurableListableBeanFactory#registerCustomEditor */
public void setCustomEditors(Map<Class<?>, Class<? extends PropertyEditor>> customEditors) { this.customEditors = customEditors; } @Override 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); } } }