Spring Framework之自定义属性编辑器

什么是spring属性编辑器?

简单点,就是在属性注入的时候,能够将配置的String类型转为bean属性真正的类型。
例如在spring的xml配置文件中配置

<bean id="sqlSessionFactorybbcbaseshop" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="configLocation" value="classpath:mybatis/mybatis-sql.xml"></property>
		<property name="dataSource" ref="dataSourceA"></property>
</bean>

这里配置的configLocation看起来是个地址,是字符串类型,但是在SqlSessionFactoryBean中是Resource类型

private Resource configLocation;

然后进行一系列操作并不会报错,是因为spring内部有个默认的属性编辑器ResourceEditor将属性转换了

xmlConfigBuilder = new XMLConfigBuilder(configLocation.getInputStream(), null, configurationProperties);
            configuration = xmlConfigBuilder.getConfiguration();

ResourceEditor属性编辑器

public class ResourceEditor extends PropertyEditorSupport {
    private final ResourceLoader resourceLoader;
    @Nullable
    private PropertyResolver propertyResolver;
    private final boolean ignoreUnresolvablePlaceholders;

    public ResourceEditor() {
        this(new DefaultResourceLoader(), (PropertyResolver)null);
    }

    public ResourceEditor(ResourceLoader resourceLoader, @Nullable PropertyResolver propertyResolver) {
        this(resourceLoader, propertyResolver, true);
    }

    public ResourceEditor(ResourceLoader resourceLoader, @Nullable PropertyResolver propertyResolver, boolean ignoreUnresolvablePlaceholders) {
        Assert.notNull(resourceLoader, "ResourceLoader must not be null");
        this.resourceLoader = resourceLoader;
        this.propertyResolver = propertyResolver;
        this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
    }

    public void setAsText(String text) {
        if (StringUtils.hasText(text)) {
            String locationToUse = this.resolvePath(text).trim();
            this.setValue(this.resourceLoader.getResource(locationToUse));
        } else {
            this.setValue((Object)null);
        }

    }

    protected String resolvePath(String path) {
        if (this.propertyResolver == null) {
            this.propertyResolver = new StandardEnvironment();
        }

        return this.ignoreUnresolvablePlaceholders ? this.propertyResolver.resolvePlaceholders(path) : this.propertyResolver.resolveRequiredPlaceholders(path);
    }

    @Nullable
    public String getAsText() {
        Resource value = (Resource)this.getValue();

        try {
            return value != null ? value.getURL().toExternalForm() : "";
        } catch (IOException var3) {
            return null;
        }
    }
}

重点关注setAsText(String text)方法,实现了属性转换。

自定义属性编辑器

自定义日期转换属性编辑器

仿照ResourceEditor一样,继承PropertyEditorSupport接口,主要重写getAsText()setAsText(String text)方法

public class MyDateEditor extends PropertyEditorSupport {

	private List<SimpleDateFormat> list;
	{
		list = new ArrayList<SimpleDateFormat>();
		list.add(new SimpleDateFormat("yyyy-MM-dd"));
		list.add(new SimpleDateFormat("yyyy年MM月dd日"));
	}

	public String getAsText() {
		return getValue().toString();
	}

	public List<SimpleDateFormat> getList() {
		return list;
	}

	public void setList(List<SimpleDateFormat> list) {
		this.list = list;
	}

	public void setAsText(String text) throws IllegalArgumentException {
		for (SimpleDateFormat format : list) {
			try {
				Date date = format.parse(text);
				setValue(date);
				return;
			} catch (ParseException e) {

			}
		}
		throw new RuntimeException("无法转换");
	}
}
CustomEditorConfigurer添加自定义属性编辑器

在容器中,属性编辑器有两种存放方式

private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet(4);
private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap(4);

从spring加载流程知道,spring内部默认的属性编辑器放在propertyEditorRegistrarsspring内部默认的属性编辑器
我们自定义的话,可以通过CustomEditorConfigurer(它是一个BeanFactoryPostProcessor),它会将属性编辑器放入customEditors

public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered {
    protected final Log logger = LogFactory.getLog(this.getClass());
    private int order = 2147483647;
    @Nullable
    private PropertyEditorRegistrar[] propertyEditorRegistrars;
    @Nullable
    private Map<Class<?>, Class<? extends PropertyEditor>> customEditors;

    public CustomEditorConfigurer() {
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public int getOrder() {
        return this.order;
    }

    public void setPropertyEditorRegistrars(PropertyEditorRegistrar[] propertyEditorRegistrars) {
        this.propertyEditorRegistrars = propertyEditorRegistrars;
    }

    public void setCustomEditors(Map<Class<?>, Class<? extends PropertyEditor>> customEditors) {
        this.customEditors = customEditors;
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (this.propertyEditorRegistrars != null) {
            PropertyEditorRegistrar[] var2 = this.propertyEditorRegistrars;
            int var3 = var2.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                PropertyEditorRegistrar propertyEditorRegistrar = var2[var4];
                beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
            }
        }

        if (this.customEditors != null) {
            this.customEditors.forEach(beanFactory::registerCustomEditor);
        }

    }
}

可以看到,在执行postProcessBeanFactory时(spring执行BeanFactoryPostProcessor),会分别判断属性propertyEditorRegistrarscustomEditors,进而添加属性编辑器。这里实现第二种方式,对customEditors属性赋值
配置类MyConfig

@Bean
public CustomEditorConfigurer customEditorConfigurer(){
	CustomEditorConfigurer configurer = new CustomEditorConfigurer();
	Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>();
	// 参数1:转化后的类型,参数2:属性转换器
	customEditors.put(Date.class, MyDateEditor.class);
	configurer.setCustomEditors(customEditors);
	return configurer;
}

属性转换测试

@Component
public class User {
	
	@Value("浴缸")
	private String name;
	@Value("9")
    private Integer id;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Value("2019年03月11日")
    private Date date;

    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", date=" + date +
                '}';
    }

    public User(String name, Integer id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public User() {
    }
}
AnnotationConfigApplicationContext context = 
				new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean(User.class);
System.out.println(user.toString());

打印

User{name='浴缸', id=9, date=Mon Mar 11 00:00:00 CST 2019}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值