1 /* 2 * Copyright 2002-2013 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.beans.factory.config; 18 19 import java.beans.PropertyEditor; 20 import java.util.Map; 21 22 import org.apache.commons.logging.Log; 23 import org.apache.commons.logging.LogFactory; 24 25 import org.springframework.beans.BeansException; 26 import org.springframework.beans.PropertyEditorRegistrar; 27 import org.springframework.core.Ordered; 28 import org.springframework.util.ClassUtils; 29 30 /** 31 * {@link BeanFactoryPostProcessor} implementation that allows for convenient 32 * registration of custom {@link PropertyEditor property editors}. 33 * 34 * <p>In case you want to register {@link PropertyEditor} instances, 35 * the recommended usage as of Spring 2.0 is to use custom 36 * {@link PropertyEditorRegistrar} implementations that in turn register any 37 * desired editor instances on a given 38 * {@link org.springframework.beans.PropertyEditorRegistry registry}. Each 39 * PropertyEditorRegistrar can register any number of custom editors. 40 * 41 * <pre class="code"> 42 * <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> 43 * <property name="propertyEditorRegistrars"> 44 * <list> 45 * <bean class="mypackage.MyCustomDateEditorRegistrar"/> 46 * <bean class="mypackage.MyObjectEditorRegistrar"/> 47 * </list> 48 * </property> 49 * </bean> 50 * </pre> 51 * 52 * <p> 53 * It's perfectly fine to register {@link PropertyEditor} <em>classes</em> via 54 * the {@code customEditors} property. Spring will create fresh instances of 55 * them for each editing attempt then: 56 * 57 * <pre class="code"> 58 * <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> 59 * <property name="customEditors"> 60 * <map> 61 * <entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/> 62 * <entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/> 63 * </map> 64 * </property> 65 * </bean> 66 * </pre> 67 * 68 * <p> 69 * Note, that you shouldn't register {@link PropertyEditor} bean instances via 70 * the {@code customEditors} property as {@link PropertyEditor}s are stateful 71 * and the instances will then have to be synchronized for every editing 72 * attempt. In case you need control over the instantiation process of 73 * {@link PropertyEditor}s, use a {@link PropertyEditorRegistrar} to register 74 * them. 75 * 76 * <p> 77 * Also supports "java.lang.String[]"-style array class names and primitive 78 * class names (e.g. "boolean"). Delegates to {@link ClassUtils} for actual 79 * class name resolution. 80 * 81 * <p><b>NOTE:</b> Custom property editors registered with this configurer do 82 * <i>not</i> apply to data binding. Custom editors for data binding need to 83 * be registered on the {@link org.springframework.validation.DataBinder}: 84 * Use a common base class or delegate to common PropertyEditorRegistrar 85 * implementations to reuse editor registration there. 86 * 87 * @author Juergen Hoeller 88 * @since 27.02.2004 89 * @see java.beans.PropertyEditor 90 * @see org.springframework.beans.PropertyEditorRegistrar 91 * @see ConfigurableBeanFactory#addPropertyEditorRegistrar 92 * @see ConfigurableBeanFactory#registerCustomEditor 93 * @see org.springframework.validation.DataBinder#registerCustomEditor 94 */ 95 public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered { 96 97 protected final Log logger = LogFactory.getLog(getClass()); 98 99 private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered 100 101 private PropertyEditorRegistrar[] propertyEditorRegistrars; 102 103 private Map<Class<?>, Class<? extends PropertyEditor>> customEditors; 104 105 106 public void setOrder(int order) { 107 this.order = order; 108 } 109 110 @Override 111 public int getOrder() { 112 return this.order; 113 } 114 115 /** 116 * Specify the {@link PropertyEditorRegistrar PropertyEditorRegistrars} 117 * to apply to beans defined within the current application context. 118 * <p>This allows for sharing {@code PropertyEditorRegistrars} with 119 * {@link org.springframework.validation.DataBinder DataBinders}, etc. 120 * Furthermore, it avoids the need for synchronization on custom editors: 121 * A {@code PropertyEditorRegistrar} will always create fresh editor 122 * instances for each bean creation attempt. 123 * @see ConfigurableListableBeanFactory#addPropertyEditorRegistrar 124 */ 125 public void setPropertyEditorRegistrars(PropertyEditorRegistrar[] propertyEditorRegistrars) { 126 this.propertyEditorRegistrars = propertyEditorRegistrars; 127 } 128 129 /** 130 * Specify the custom editors to register via a {@link Map}, using the 131 * class name of the required type as the key and the class name of the 132 * associated {@link PropertyEditor} as value. 133 * @see ConfigurableListableBeanFactory#registerCustomEditor 134 */ 135 public void setCustomEditors(Map<Class<?>, Class<? extends PropertyEditor>> customEditors) { 136 this.customEditors = customEditors; 137 } 138 139 140 @Override 141 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 142 if (this.propertyEditorRegistrars != null) { 143 for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) { 144 beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar); 145 } 146 } 147 if (this.customEditors != null) { 148 for (Map.Entry<Class<?>, Class<? extends PropertyEditor>> entry : this.customEditors.entrySet()) { 149 Class<?> requiredType = entry.getKey(); 150 Class<? extends PropertyEditor> propertyEditorClass = entry.getValue(); 151 beanFactory.registerCustomEditor(requiredType, propertyEditorClass); 152 } 153 } 154 } 155 156 }