`
anyeeye
  • 浏览: 143811 次
  • 来自: ...
社区版块
存档分类
最新评论

关于Spring属性编辑器详解

阅读更多
最近刚在研究Spring的编辑器,发现很有意思,刚好galaxystar起了一个这样贴,我想对PropertyEditor作一个详细的整理会对大家有益,特定启了这个新帖。

所谓的PropertyEditor,顾名思义,就是属性编辑器。由于Bean属性通过配置文档以字符串了方式为属性赋值,所以必须有一个“东东”负责将这个字符串转换为属性的直接对象,如属性的类型为int,那么编辑器要做的工作就是int i = Integer.parseInt("1");
Spring为一般的属性类型提供了默认的编辑器,BeanWrapperImpl是Spring框架中重要的类,它负责对注入的Bean进行包装化的管理,常见属性类型对应的编辑器即在该类中通过以下代码定义:



代码
private void registerDefaultEditors()  
    {  
        // Simple editors, without parameterization capabilities.  
        // The JDK does not contain a default editor for any of these target types.  
        this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());  
        this.defaultEditors.put(Class.class, new ClassEditor());  
        this.defaultEditors.put(File.class, new FileEditor());  
        this.defaultEditors.put(InputStream.class, new InputStreamEditor());  
        this.defaultEditors.put(Locale.class, new LocaleEditor());  
        this.defaultEditors.put(Properties.class, new PropertiesEditor());  
        this.defaultEditors.put(Resource[].class,  
                                new ResourceArrayPropertyEditor());  
        this.defaultEditors.put(String[].class, new StringArrayPropertyEditor());  
        this.defaultEditors.put(URL.class, new URLEditor());  
 
        // Default instances of collection editors.  
        // Can be overridden by registering custom instances of those as custom editors.  
        this.defaultEditors.put(Collection.class,  
                                new CustomCollectionEditor(Collection.class));  
        this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));  
        this.defaultEditors.put(SortedSet.class,  
                                new CustomCollectionEditor(SortedSet.class));  
        this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));  
 
        // Default instances of character and boolean editors.  
        // Can be overridden by registering custom instances of those as custom editors.  
        PropertyEditor characterEditor = new CharacterEditor(false);  
        PropertyEditor booleanEditor = new CustomBooleanEditor(false);  
 
        // The JDK does not contain a default editor for char!  
        this.defaultEditors.put(char.class, characterEditor);  
        this.defaultEditors.put(Character.class, characterEditor);  
 
        // Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.  
        this.defaultEditors.put(boolean.class, booleanEditor);  
        this.defaultEditors.put(Boolean.class, booleanEditor);  
 
        // The JDK does not contain default editors for number wrapper types!  
        // Override JDK primitive number editors with our own CustomNumberEditor.  
        PropertyEditor byteEditor = new CustomNumberEditor(Byte.class, false);  
        PropertyEditor shortEditor = new CustomNumberEditor(Short.class, false);  
        PropertyEditor integerEditor = new CustomNumberEditor(Integer.class, false);  
        PropertyEditor longEditor = new CustomNumberEditor(Long.class, false);  
        PropertyEditor floatEditor = new CustomNumberEditor(Float.class, false);  
        PropertyEditor doubleEditor = new CustomNumberEditor(Double.class, false);  
 
        this.defaultEditors.put(byte.class, byteEditor);  
        this.defaultEditors.put(Byte.class, byteEditor);  
 
        this.defaultEditors.put(short.class, shortEditor);  
        this.defaultEditors.put(Short.class, shortEditor);  
 
        this.defaultEditors.put(int.class, integerEditor);  
        this.defaultEditors.put(Integer.class, integerEditor);  
 
        this.defaultEditors.put(long.class, longEditor);  
        this.defaultEditors.put(Long.class, longEditor);  
 
        this.defaultEditors.put(float.class, floatEditor);  
        this.defaultEditors.put(Float.class, floatEditor);  
 
        this.defaultEditors.put(double.class, doubleEditor);  
        this.defaultEditors.put(Double.class, doubleEditor);  
 
        this.defaultEditors.put(BigDecimal.class,  
                                new CustomNumberEditor(BigDecimal.class, false));  
        this.defaultEditors.put(BigInteger.class,  
                                new CustomNumberEditor(BigInteger.class, false));  
    }  


但是,并非Bean的属性都是这些常见的类型,如果你的Bean需要注入一个自定义类型的属性,而又想享受IoC的好处,那么就只得自己开干,提供一个自定义的PropertyEditor了。
下面,分几个步骤来说明,定义一个自定义PropertyEditor的过程。
1)首先,碰到的问题即是,要如何编辑自己的PropertyEditor,其实需要了解一点java.beans包的知识,在该包中,有一个java.beans.PropertyEditor的接口,它定义了一套接口方法(12个),即通过这些方法如何将一个String变成内部的一个对象,这两个方法是比较重要的:
a)setValue(Object value) 直接设置一个对象,一般不直接用该方法设置属性对象
b)setAsText(String text) 通过一个字符串来构造对象,一般在此方法中解析字符串,将构造一个
类对象,调用setValue(Object)来完成属性对象设置操作。

2)实现所有的接口方法是麻烦的,java.beans.PropertyEditorSupport 适时登场,一般情况下,我们通过扩展这个方便类即可。

3)编写完后,就是在Spring配置文件中注册该属性类型编辑器的问题,Spring提供了专门的注册工具类
org.springframework.beans.factory.config.CustomEditorConfigurer,它负责将属性类型和
属性编辑器关联起来。到时BeanFactory注入Bean的属性时,即会在注册表中查找属性类型对应的编辑器。

下面给出一个小例子,例子先作一个简单描述:
1)Person 需要进行属性注入的Bean,有两个属性 一个是name,一个是address Address是一个类
2)Address Person的属性类型,本身有3个属性。
3)AddressPropertyEditor Address类型对应的属性编辑器。

开工:
1.Person.java


代码
package com.stamen.propedit;  
 
import org.apache.commons.lang.builder.ToStringBuilder;  
 
public class Person {  
    private String name;  
 
    private Address address;  
 
    public Address getAddress() {  
        return address;  
    }  
 
    public void setAddress(Address address) {  
        this.address = address;  
    }  
 
    public String getName() {  
        return name;  
    }  
 
    public void setName(String name) {  
        this.name = name;  
    }  
    public String toString() {  
        return ToStringBuilder.reflectionToString(this);  
    }  
}   



2.Address.java

代码
package com.stamen.propedit;  
import org.apache.commons.lang.builder.ToStringBuilder;  
public class Address {  
    private String street;  
 
    private String doorNum;  
 
    private String postCode;  
 
    public String getDoorNum() {  
        return doorNum;  
    }  
 
    public void setDoorNum(String doorNum) {  
        this.doorNum = doorNum;  
    }  
 
    public String getPostCode() {  
        return postCode;  
    }  
 
    public void setPostCode(String postCode) {  
        this.postCode = postCode;  
    }  
 
    public String getStreet() {  
        return street;  
    }  
 
    public void setStreet(String street) {  
        this.street = street;  
    }  
      
    public String toString() {  
        return ToStringBuilder.reflectionToString(this);  
    }  
 
}  
  



AddressPropertyEditor.java

代码
package com.stamen.propedit;  
 
import java.beans.PropertyEditorSupport;  
import java.util.Date;  
 
import org.springframework.util.StringUtils;  
public class AddressPropertyEditor extends PropertyEditorSupport{  
    //支持的格式为 streeValue,doorNumValue,postCode  
    public void setAsText(String text)  
    {  
        System.out.println("使用自己的编辑器。");  
        if (text == null || !StringUtils.hasText(text)) {  
            throw new IllegalArgumentException("老大,不能为空啊!");  
        }  
        else 
        {  
            String[] strArr = StringUtils.tokenizeToStringArray(text,",");  
            Address add = new Address();  
            add.setStreet(strArr[0]);  
            add.setDoorNum(strArr[1]);  
            add.setPostCode(strArr[2]);  
            setValue(add);  
        }  
    }  
      
    public String getAsText()  
    {  
        Address add = (Address)getValue();  
        return ""+add;  
    }  
}  
  


打开Spring配置文件,添上这两个配置项:


代码
  <bean id="customEditorConfigurer"  class="org.springframework.beans.factory.config.CustomEditorConfigurer"> 
  <property name="customEditors"> 
    <map> 
      <entry key="com.stamen.propedit.Address"> <!-- 属性类型 --> 
        <bean class="com.stamen.propedit.AddressPropertyEditor"/> <!--对应Address的编辑器 --> 
      </entry> 
    </map> 
  </property> 
</bean> 
 
<bean id="person" class="com.stamen.propedit.Person"> 
    <property name="name" value="Tom"/> 
    <property name="address" value="朝阳区,Soho 1601,010101"/> 
</bean> 

分享到:
评论
3 楼 coffeesweet 2010-05-27  
java.beans确实应该好好看看,了解一下,楼主的例子很好,谢谢了
2 楼 fangbiao23 2007-06-21  


代码有:
package PropertyEditors;

/**
* @author Administrator
*
*/
public class MyExpectType {
private String text;

/**
* @return text
*/
public String getText() {
return text;
}

/**
* @param text 要设置的 text
*/
public MyExpectType(String text) {
this.text = text;
}

}
/******************************************/
package PropertyEditors;
import java.beans.PropertyEditorSupport;
/**
* @author Administrator
*
*/
public class MyExpectTypeEditor extends PropertyEditorSupport{
private String format;

public void setFormat(String format) {
this.format = format;
}

public void setAsTest(String text){
//System.out.println("修改前类型:"+text.getClass().getSimpleName());
if(format != null || format.equals("upperCase"))
text = text.toUpperCase();
MyExpectType myType = new MyExpectType(text);
setValue(myType);
}
}
/********************************************/
package PropertyEditors;

/**
* @author Administrator
*
*/
public class DependsOnExpectType {
private MyExpectType myType;

/**
* @return myType
*/
public MyExpectType getMyType() {
return myType;
}

/**
* @param myType 要设置的 myType
*/
public void setMyType(MyExpectType myType) {
this.myType = myType;
}
}
/***************************************/
package PropertyEditors;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.CustomEditorConfigurer;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
* @author Administrator
*
*/
public class MyEditorUsage {
   
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO 自动生成方法存根
//String path[] = new String[]{"pEditor.xml","plugins.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext("plugins.xml");
DependsOnExpectType someBean = (DependsOnExpectType)ctx.getBean("someBean");
System.out.println("修改后类型:"+someBean .getClass().getSimpleName());
System.out.println("修改效果:"+someBean.getMyType().getText());
}

}
/********************XML文件*******************/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEANS//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="customEditorConfigurer"
   class="org.springframework.beans.factory.config.CustomEditorConfigurer">
   <property name="customEditors">
   <map>
   <entry key="PropertyEditors.MyExpectType">
   <bean class="PropertyEditors.MyExpectTypeEditor">
   <property name="format">
   <value>upperCase</value>
   </property>
   </bean>
   </entry>
   </map> 
       </property>
</bean>
<bean id="someBean"
  class="PropertyEditors.DependsOnExpectType">
<property name="myType" value="fangbiao"/>
</bean>
</beans>

1 楼 fangbiao23 2007-06-21  
我也做了个相应的例子,但就总是报错:
错误信息为:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someBean' defined in class path resource [plugins.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.lang.String] to required type [PropertyEditors.MyExpectType] for property 'myType'; nested exception is java.lang.IllegalArgumentException: fangbiao
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessException details (1) are:
PropertyAccessException 1:
org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.lang.String] to required type [PropertyEditors.MyExpectType] for property 'myType'; nested exception is java.lang.IllegalArgumentException: fangbiao
Caused by: java.lang.IllegalArgumentException: fangbiao
at java.beans.PropertyEditorSupport.setAsText(PropertyEditorSupport.java:166)
at org.springframework.beans.TypeConverterDelegate.convertValue(TypeConverterDelegate.java:268)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:189)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:139)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:772)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:606)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValue(AbstractPropertyAccessor.java:49)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:74)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:57)
at org.springframework.beans.factory.support.AbstractBeanFactory.applyPropertyValues(AbstractBeanFactory.java:836)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1026)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:809)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:425)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:250)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:247)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:161)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:273)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:346)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:92)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:77)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:68)
at PropertyEditors.MyEditorUsage.main(MyEditorUsage.java:25)

相关推荐

    Spring-Reference_zh_CN(Spring中文参考手册)

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的...

    Spring 2.0 开发参考手册

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建...

    Spring.3.x企业应用开发实战(完整版).part2

    5.2.2 Spring默认属性编辑器 5.2.3 自定义属性编辑器 5.3 使用外部属性文件 5.3.1 使用外部属性文件 5.3.2 使用加密的属性文件 5.3.3 属性文件自身的引用 5.4 引用Bean的属性值 5.5 国际化信息 5.5.1 基础知识 5.5.2...

    Spring中文帮助文档

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建...

    Spring API

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建...

    spring chm文档

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建...

    Spring2.0学习笔记

    1、ICO环境的搭建 2、属性注入 3、自定义属性编辑器 4、AOP实现 5、事务处理 6、Spring事务配置的五种方式 详解 7、Struts与Spring集成方案

    Spring3.x企业应用开发实战(完整版) part1

    5.2.2 Spring默认属性编辑器 5.2.3 自定义属性编辑器 5.3 使用外部属性文件 5.3.1 使用外部属性文件 5.3.2 使用加密的属性文件 5.3.3 属性文件自身的引用 5.4 引用Bean的属性值 5.5 国际化信息 5.5.1 基础知识 5.5.2...

    springboot项目整合.zip

    第二篇:SpringBoot配置详解] 第三篇:SpringBoot日志配置] 第四篇:整合Thymeleaf模板] 第五篇:使用JdbcTemplate访问数据库] 第六篇:整合SpringDataJpa] 第七篇:整合Mybatis] 第八篇:通用Mapper与...

    Step By Step写测试(书签版).pdf

    《Step By Step写测试》介绍使用 JTESTER 写单元测试,作者吴大瑞,pdf 格式,大小 1.8MB。本书带有 pdf 书签,方便读者阅读。 目录: Jtester的项目配置 1 TestNG测试 ...7.6 使用SQL Editor编辑器 覆盖率统计

    本科毕业设计+基于Springboot+JPA+semantic开发的个人博客系统

    集成了markdown编辑器,markdown内容转化器,中文排版 项目框架: 前端 static :为js,css,images以及一些集成工具的样式 templates:分别为后台管理html,错误html,前台显示html 后端 依次是javabean,配置类...

    webx3框架指南PDF教程附学习Demo

    • 扩展性 —— Webx 3.0对Spring做了扩展,使Spring Bean不再是“bean”,而是升级成“组件”。一个组件可以扩展另一个组件,也可以被其它组件扩展。这种机制造就了Webx的非常好的扩展性,且比未经扩展的Spring更易...

    swing界面设计之JTree

    定义 bean 属性 21 创建 to-do 列表:创建一个可重用组件并在表中显示数据 23 创建一个可重用的面板 23 将 bean 组合在一起 24 添加一个表并重用这个面板 26 定义表模型 28 显示列表中的项 29 创建 to-do 列表:完成...

    Maven权威指南 很精典的学习教程,比ANT更好用

    平台分类器 11.8. 小结 12. Maven Assemblies 12.1. Introduction 12.2. Assembly Basics 12.2.1. Predefined Assembly Descriptors 12.2.2. Building an Assembly 12.2.3. Assemblies as Dependencies ...

    JBPM4工作流应用开始指南.rar

    26 2.3 安装脚本详解 27 2.3.1 关于配置文件 30 2.3.2 关于依赖库 31 2.4 安装到JBoss 31 2.5 安装到Tomcat 32 2.6 基于Web的Signavio流程设计器 33 2.6.1 jBPM Web流程设计器简介 33 2.6.2 独立安装Signavio 34 ...

    asp.net知识库

    关于能自定义格式的、支持多语言的、支持多数据库的代码生成器的想法 发布Oracle存储过程包c#代码生成工具(CodeRobot) New Folder XCodeFactory3.0完全攻略--序 XCodeFactory3.0完全攻略--基本思想 XCodeFactory...

    平板显示发展史

    关于一个选择器XML的小程序 C++控制台计算器(能识别括号) Java面试宝典 VC写的蝴蝶会动的时钟 清华大学C语言课件【超详细_很强大】 Struts,Hibernate,Spring集成开发宝典.pdf asp.net mvc教程 jquery-ui-1.9.2....

    整理后java开发全套达内学习笔记(含练习)

    Iterator [java] 迭代器, 迭代程序 legal 合法的 ['li:gәl] log n.日志,记录 [lɒg] native (关键字) ?? ['neitiv] nested [java] 嵌套的 ['nestid] '如:内部类(nested classes) Object [java] 对象 ['ɒbdʒ...

Global site tag (gtag.js) - Google Analytics