spring中自定义属性编辑器如何注入和取出的流程(通过CustomEditorConfigurer)

本文介绍了在Spring中如何自定义属性编辑器,并通过CustomEditorConfigurer进行注入,以实现字符串到对象的转换。文章详细阐述了注入的原理流程,包括CustomEditorConfigurer实现BeanFactoryPostProcessor接口并在postProcessBeanFactory方法中进行配置,以及在bean实例化过程中如何调用转换方法。通过调试,展示了在TypeConverterDelegate中如何找到并使用自定义的属性编辑器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们可以自定义属性编辑器对类中的实例对象赋值,通过string类型值转换成对象类型值进行赋值。当我们使用下列方式注册时:

<bean id="PropertyEditorConfigurer1"
        class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="renchaofeng_propertyEditor.Education" value="renchaofeng_propertyEditor.TestPropertyEditor"/>
            </map>
        </property>
    </bean>

 上面方式把我们自己定义的属性编辑器renchaofeng_propertyEditor.TestPropertyEditor注入到org.springframework.beans.factory.config.CustomEditorConfigurer的customEditors属性中,就可以达到转换的效果,那么原理流程是怎样的呢?如下:

org.springframework.beans.factory.config.CustomEditorConfigurer实现了BeanFactoryPostProcessor接口,所以会实现postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法,在此方法中代码如下:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		if (this.propertyEditorRegistrars != null) {
			for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
				beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
			}
		}
		if (this.customEditors != null) {//此处集合customEditors中有我们的属性编辑器renchaofeng_propertyEditor.TestPropertyEditor
			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);//把我们自定义属性编辑器注册入beanFactory中以备后续使用
			}
		}
	}

上面是注入过程,下面在什么怎么取出使用呢?答案如下: 在bean的实例化过程中使用,在AbstractBeanFactory类中创建bean方法中,如下:

@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
//......前面源码省略.....
// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);//在此处进行获取我们自定义属性编辑器
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

 进入convertIfNecessary中一路点击下去进入类TypeConverterSupport中的方法doConvert,如下:

private <T> T doConvert(Object value, Class<T> requiredType, MethodParameter methodParam, Field field)
			throws TypeMismatchException {
		try {
			if (field != null) {
				return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
			}
			else {
				return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);//通过此方法进入点击进去
			}
		}
		catch (ConverterNotFoundException ex) {
			throw new ConversionNotSupportedException(value, requiredType, ex);
		}
		catch (ConversionException ex) {
			throw new TypeMismatchException(value, requiredType, ex);
		}
		catch (IllegalStateException ex) {
			throw new ConversionNotSupportedException(value, requiredType, ex);
		}
		catch (IllegalArgumentException ex) {
			throw new TypeMismatchException(value, requiredType, ex);
		}
	}

 点击进去进入类TypeConverterDelegate中找到方法convertIfNecessary,如下:

/**
	 * Convert the value to the required type (if necessary from a String),
	 * for the specified property.
	 * @param propertyName name of the property
	 * @param oldValue the previous value, if available (may be {@code null})
	 * @param newValue the proposed new value
	 * @param requiredType the type we must convert to
	 * (or {@code null} if not known, for example in case of a collection element)
	 * @param typeDescriptor the descriptor for the target property or field
	 * @return the new value, possibly the result of type conversion
	 * @throws IllegalArgumentException if type conversion failed
	 */
	@SuppressWarnings("unchecked")
	public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
			Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
// Custom editor for this type?
		PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);//此处就会查找取出我们自定义的属性编辑器进行使用

		ConversionFailedException conversionAttemptEx = null;

		// No custom editor but custom ConversionService specified?
		ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
		if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
			TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
			if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
				try {
					return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
				}
				catch (ConversionFailedException ex) {
					// fallback to default conversion logic below
					conversionAttemptEx = ex;
				}
			}
		}

		Object convertedValue = newValue;
//.....后面源码省略。。。。。
}

通过debug调试取出我们的属性编辑器如下:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值