Spring 源码学习(3) —— 增加属性注册编辑器

创建一个实体类UserManager:

 1 /**
 2  * @filename: UserManager.java
 3  * @desc 增加属性编辑器功能测试实体类
 4  * @author: Wang Chinda
 5  * @blog http://www.cnblogs.com/goodcheap
 6  * @date: 2018-05-25 9:32
 7  * @version: v1.0
 8  * @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
 9  * @modify_history: -
10  * 20180525   Wang Chinda   create
11  * 20180525   Wang Chinda   modify   method()
12  */
13 package com.itdoc.learn.source.add.attribute;
14 
15 import java.util.Date;
16 
17 /**
18  * @desc 增加属性编辑器功能测试实体类
19  * @author Wang Chinda
20  * @create 2018-05-25 9:32
21  */
22 public class UserManager {
23 
24     private Date dateValue;
25 
26 
27     public Date getDateValue() {
28         return dateValue;
29     }
30 
31     public void setDateValue(Date dateValue) {
32         this.dateValue = dateValue;
33     }
34 
35     @Override
36     public String toString() {
37         return "UserManager{" +
38                 "dateValue=" + dateValue +
39                 '}';
40     }
41 }

 创建配置文件:

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5 
6     <bean id="getUserManager" class="com.itdoc.learn.source.add.attribute.UserManager">
7         <property name="dateValue" value="2018-05-25"/>
8     </bean>
9 </beans>

测试:

 1 /**
 2  * @filename: AtrributeClient.java
 3  * @desc 增加属性编辑器测试客户端
 4  * @author: Wang Chinda
 5  * @blog http://www.cnblogs.com/goodcheap
 6  * @date: 2018-05-25 9:34
 7  * @version: v1.0
 8  * @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
 9  * @modify_history: -
10  * 20180525   Wang Chinda   create
11  * 20180525   Wang Chinda   modify   method()
12  */
13 package com.itdoc.learn.source.add.attribute;
14 
15 import org.springframework.context.ApplicationContext;
16 import org.springframework.context.support.ClassPathXmlApplicationContext;
17 
18 /**
19  * @desc 增加属性编辑器测试客户端
20  * @author Wang Chinda
21  * @create 2018-05-25 9:34
22  */
23 public class AtrributeClient {
24 
25     public static void main(String[] args) {
26         ApplicationContext app = new ClassPathXmlApplicationContext("test/add-attribute-editor-test.xml");
27         UserManager userManager = (UserManager) app.getBean("getUserManager");
28         System.out.println(userManager);
29     }
30 
31 }

控制台显示:

五月 25, 2018 9:38:19 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2ef9b8bc: startup date [Fri May 25 09:38:19 CST 2018]; root of context hierarchy
五月 25, 2018 9:38:19 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [test/add-attribute-editor-test.xml]
五月 25, 2018 9:38:19 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3c22fc4c: defining beans [getUserManager]; root of factory hierarchy
五月 25, 2018 9:38:19 上午 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
信息: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3c22fc4c: defining beans [getUserManager]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getUserManager' defined in class path resource [test/add-attribute-editor-test.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'dateValue'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property 'dateValue': no matching editors or conversion strategy found
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.itdoc.learn.source.add.attribute.AtrributeClient.main(AtrributeClient.java:26)
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'dateValue'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property 'dateValue': no matching editors or conversion strategy found
    at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:463)
    at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:494)
    at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:488)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1433)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1392)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1128)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    ... 11 more
Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property 'dateValue': no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:264)
    at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:448)
    ... 17 more

出错原因: UserManager中的dateValue属性是Date类型, 而XML中配置的却是String类型。

Spring针对此问题提供了两种解决方案:

1. 使用自定义属性编辑器

使用自定义属性编辑器, 通过继承PropertyEditorSupport, 重写setAsText方法。

1). 编写自定义的属性编辑器:

 1 /**
 2  * @filename: DatePropertyEditor.java
 3  * @desc 自定义Date属性编辑器
 4  * @author: Wang Chinda
 5  * @blog http://www.cnblogs.com/goodcheap
 6  * @date: 2018-05-25 9:53
 7  * @version: v1.0
 8  * @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
 9  * @modify_history: -
10  * 20180525   Wang Chinda   create
11  * 20180525   Wang Chinda   modify   method()
12  */
13 package com.itdoc.learn.source.add.attribute;
14 
15 import java.beans.PropertyEditorSupport;
16 import java.text.ParseException;
17 import java.text.SimpleDateFormat;
18 import java.util.Date;
19 
20 /**
21  * @desc 自定义Date属性编辑器
22  * @author Wang Chinda
23  * @create 2018-05-25 9:53
24  */
25 public class DatePropertyEditor extends PropertyEditorSupport {
26 
27     private String format = "yy-MM-dd";
28 
29     public void setFormat(String format) {
30         this.format = format;
31     }
32 
33     @Override
34     public void setAsText(String text) throws IllegalArgumentException {
35         System.out.println("text: " + text);
36         SimpleDateFormat dateFormat = new SimpleDateFormat(format);
37         try {
38             Date date = dateFormat.parse(text);
39             this.setValue(date);
40         } catch (ParseException e) {
41             e.printStackTrace();
42         }
43         super.setAsText(text);
44     }
45 }

2). 将自定义的属性编辑注册到Spring中:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 5 
 6     <bean id="getUserManager" class="com.itdoc.learn.source.add.attribute.UserManager">
 7         <property name="dateValue" value="2018-05-25"/>
 8     </bean>
 9 
10     <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
11         <property name="customEditors">
12             <map>
13                 <entry key="java.util.Date">
14                     <bean class="com.itdoc.learn.source.add.attribute.DatePropertyEditor"/>
15                 </entry>
16             </map>
17         </property>
18     </bean>
19 </beans>

 控制台输出:

五月 25, 2018 10:11:34 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2ef9b8bc: startup date [Fri May 25 10:11:34 CST 2018]; root of context hierarchy
五月 25, 2018 10:11:34 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [test/add-attribute-editor-test.xml]
五月 25, 2018 10:11:34 上午 org.springframework.beans.factory.config.CustomEditorConfigurer postProcessBeanFactory
警告: Passing PropertyEditor instances into CustomEditorConfigurer is deprecated: use PropertyEditorRegistrars or PropertyEditor class names instead. Offending key [java.util.Date; offending editor instance: com.itdoc.learn.source.add.attribute.DatePropertyEditor@6302bbb1
五月 25, 2018 10:11:34 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6af93788: defining beans [getUserManager,org.springframework.beans.factory.config.CustomEditorConfigurer#0]; root of factory hierarchy
text: 2018-05-25
UserManager{dateValue=Fri May 25 00:00:00 CST 2018}

 2. 注册Spring自带的属性编辑器CustomDateEditor

 1).定义属性编辑器:

 1 /**
 2  * @filename: CustomDatePropertyEditor.java
 3  * @desc 实现Spring提供的自定义时间编辑器
 4  * @author: Wang Chinda
 5  * @blog http://www.cnblogs.com/goodcheap
 6  * @date: 2018-05-25 10:18
 7  * @version: v1.0
 8  * @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
 9  * @modify_history: -
10  * 20180525   Wang Chinda   create
11  * 20180525   Wang Chinda   modify   method()
12  */
13 package com.itdoc.learn.source.add.attribute;
14 
15 import org.springframework.beans.PropertyEditorRegistrar;
16 import org.springframework.beans.PropertyEditorRegistry;
17 import org.springframework.beans.propertyeditors.CustomDateEditor;
18 
19 import java.text.SimpleDateFormat;
20 import java.util.Date;
21 
22 /**
23  * @desc 实现Spring提供的属性编辑器注册器, 应用CustomDateEditor
24  * @author Wang Chinda
25  * @create 2018-05-25 10:18
26  */
27 public class CustomDatePropertyEditor implements PropertyEditorRegistrar {
28 
29     @Override
30     public void registerCustomEditors(PropertyEditorRegistry registry) {
31         registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yy-MM-dd"), true));
32     }
33 }

2).注册到Spring中

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 5 
 6     <bean id="getUserManager" class="com.itdoc.learn.source.add.attribute.UserManager">
 7         <property name="dateValue" value="2018-05-25"/>
 8     </bean>
 9 
10     <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
11         <property name="propertyEditorRegistrars">
12             <list>
13                 <bean class="com.itdoc.learn.source.add.attribute.CustomDatePropertyEditor"/>
14             </list>
15         </property>
16     </bean>
17 </beans>

此处我换了另一个配置文件。

测试:

 1 /**
 2  * @filename: AtrributeClient.java
 3  * @desc 增加属性编辑器测试客户端
 4  * @author: Wang Chinda
 5  * @blog http://www.cnblogs.com/goodcheap
 6  * @date: 2018-05-25 9:34
 7  * @version: v1.0
 8  * @copyright: Copyright © 2018 ༄ྂ祸ྂྂ害ོ༘苍ྂྂ生ོ༘࿐ྂ 版权所有
 9  * @modify_history: -
10  * 20180525   Wang Chinda   create
11  * 20180525   Wang Chinda   modify   method()
12  */
13 package com.itdoc.learn.source.add.attribute;
14 
15 import org.springframework.context.ApplicationContext;
16 import org.springframework.context.support.ClassPathXmlApplicationContext;
17 
18 /**
19  * @desc 增加属性编辑器测试客户端
20  * @author Wang Chinda
21  * @create 2018-05-25 9:34
22  */
23 public class AtrributeClient {
24 
25     public static void main(String[] args) {
26         ApplicationContext app = new ClassPathXmlApplicationContext("test/customEditor.xml");
27         UserManager userManager = (UserManager) app.getBean("getUserManager");
28         System.out.println(userManager);
29     }
30 
31 }

GitHub源码: https://github.com/wcd19901010/spring-01

原文地址:https://www.cnblogs.com/chinda/p/9087095.html