6.5.2-spring功能扩展-增加属性编辑器(2)

spring功能扩展-增加属性编辑器(2)

上篇文章通过一个例子描述了如何改变User实例中birthday属性的类型,现在重温下大概过程:
① 定义属性编辑器 DatePropertyEditor
② 实例化 CustomEditorConfigurer 并将 DatePropertyEditor 实例添加到 customEditors 属性中

查看上篇中 CustomEditorConfigurer 源码可以发现它除了有customEditors属性,还有 propertyEditorRegistrars 属性,在本篇中将描述PropertyEditorRegistrar 的用法

@Nullable
private PropertyEditorRegistrar[] propertyEditorRegistrars;

@Nullable
private Map<Class<?>, Class<? extends PropertyEditor>> customEditors;
PropertyEditorRegistrar 使用方法
PropertyEditorRegistrar 解释

PropertyEditorRegistrar (属性编辑注册器),这是一个接口,顾名思义这个接口是用来注册属性编辑器的,以下是源码及官方解释

package org.springframework.beans;
/**
 * Interface for strategies that register custom
 * {@link java.beans.PropertyEditor property editors} with a
 * {@link org.springframework.beans.PropertyEditorRegistry property editor registry}.
 *
 * <p>This is particularly useful when you need to use the same set of
 * property editors in several different situations: write a corresponding
 * registrar and reuse that in each case.
 *
 * @author Juergen Hoeller
 * @since 1.2.6
 * @see PropertyEditorRegistry
 * @see java.beans.PropertyEditor
 */
public interface PropertyEditorRegistrar {

	/**
	 * Register custom {@link java.beans.PropertyEditor PropertyEditors} with
	 * the given {@code PropertyEditorRegistry}.
	 * <p>The passed-in registry will usually be a {@link BeanWrapper} or a
	 * {@link org.springframework.validation.DataBinder DataBinder}.
	 * <p>It is expected that implementations will create brand new
	 * {@code PropertyEditors} instances for each invocation of this
	 * method (since {@code PropertyEditors} are not threadsafe).
	 * @param registry the {@code PropertyEditorRegistry} to register the
	 * custom {@code PropertyEditors} with
	 */
	void registerCustomEditors(PropertyEditorRegistry registry);

}

如上所示PropertyEditorRegistrar 接口只有一个 registerCustomEditors方法,入参为 PropertyEditorRegistry 类型,PropertyEditorRegistry也是一个接口,上文中BeanWrapperImpl实例就实现了这个接口

PropertyEditorRegistrar 实现类定义

以下为自定义PropertyEditorRegistrar属性编辑注册器 DatePropertyEditorRegistrar的 代码:

package com.springtest.propertyEditor;

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.CustomDateEditor;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DatePropertyEditorRegistrar implements PropertyEditorRegistrar {
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }
}

在 registerCustomEditor方法中使用了spring 自带的PropertyEditor CustomDateEditor,在上文中我们也可以使用这个CustomDateEditor,只是为了 讲解PropertyEditor 和 PropertyEditorSupport 而重现实现了一遍。

在CustomEditorConfigurer 实例中添加 DatePropertyEditorRegistrar
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="propertyEditorRegistrars">
            <list>
                <bean class="com.springtest.propertyEditor.DatePropertyEditorRegistrar"></bean>
            </list>
        </property>
    </bean>

PropertyEditorRegistrar 使用方式步骤如上

PropertyEditorRegistrar 执行过程

回到 AbstractBeanFactory registerCustomEditors 方法,这个方法是在填充 BeanWrapper 实例时调用的,在上文中我们给beanFactory填充的是customEditors属性,所以 propertyEditorRegistrars中不会有我们自定义的PropertyEditorRegistrar ,进而执行 if (!this.customEditors.isEmpty()) 中的代码块,看if代码块中具体内容 registry.registerCustomEditor ,和PropertyEditorRegistrar 实现类DatePropertyEditorRegistrar 中registerCustomEditors方法中的内容一致,而PropertyEditorRegistrar 接口registerCustomEditors方法的调用时机则是在 if (!this.propertyEditorRegistrars.isEmpty()) 代码块中

protected void initBeanWrapper(BeanWrapper bw) {
	bw.setConversionService(getConversionService());
	registerCustomEditors(bw);
}

protected void registerCustomEditors(PropertyEditorRegistry registry) {
		PropertyEditorRegistrySupport registrySupport =
				(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
		if (registrySupport != null) {
			registrySupport.useConfigValueEditors();
		}
		if (!this.propertyEditorRegistrars.isEmpty()) {
			for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
				try {
					registrar.registerCustomEditors(registry);
				}
				catch (BeanCreationException ex) {
					Throwable rootCause = ex.getMostSpecificCause();
					if (rootCause instanceof BeanCurrentlyInCreationException) {
						BeanCreationException bce = (BeanCreationException) rootCause;
						String bceBeanName = bce.getBeanName();
						if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) {
							if (logger.isDebugEnabled()) {
								logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
										"] failed because it tried to obtain currently created bean '" +
										ex.getBeanName() + "': " + ex.getMessage());
							}
							onSuppressedException(ex);
							continue;
						}
					}
					throw ex;
				}
			}
		}
		if (!this.customEditors.isEmpty()) {
			this.customEditors.forEach((requiredType, editorClass) ->
					registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
		}
	}

细看两种改变属性值的方式,其实是差不多的,反倒实现PropertyEditorRegistrar 接口的方式好像还多了一个额外注册属性编辑器的动作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值