问题:spring中注入时间日期(java.util.Date)类型的属性的时候需要进行类型转换,因为spring不能直接注入Date类型。之前学习spring的时候是学的spring 2.5的版本,但是今天把spring的包都换成了spring 4.2 的,发现之前的出现错误。
具体的错误信息如下:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customEditorConfigurer' defined in file [E:\Workspaces\MyEclipse 10\spring_utildate\bin\applicationContext-beans.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.util.LinkedHashMap] to required type [java.util.Map] for property 'customEditors'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [com.zm.bean.UtilDatePropertyEditor] to required type [java.lang.Class] for property 'customEditors[java.util.Date]': PropertyEditor [org.springframework.beans.propertyeditors.ClassEditor] returned inappropriate value of type [com.zm.bean.UtilDatePropertyEditor]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:678)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:520)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.zm.test.Test.main(Test.java:11)
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.util.LinkedHashMap] to required type [java.util.Map] for property 'customEditors'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [com.zm.bean.UtilDatePropertyEditor] to required type [java.lang.Class] for property 'customEditors[java.util.Date]': PropertyEditor [org.springframework.beans.propertyeditors.ClassEditor] returned inappropriate value of type [com.zm.bean.UtilDatePropertyEditor]
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:596)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:603)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1486)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
... 11 more
Caused by: java.lang.IllegalArgumentException: Cannot convert value of type [com.zm.bean.UtilDatePropertyEditor] to required type [java.lang.Class] for property 'customEditors[java.util.Date]': PropertyEditor [org.springframework.beans.propertyeditors.ClassEditor] returned inappropriate value of type [com.zm.bean.UtilDatePropertyEditor]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:298)
at org.springframework.beans.TypeConverterDelegate.convertToTypedMap(TypeConverterDelegate.java:655)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:222)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:576)
... 17 more
经过查看日志得到的提示是,自定义的编辑器类型与要求的类型不匹配。由于之前一点代码没有改动,只是将spring 2.0 的包换成了spring 4.0的包,因此,感觉应该不是代码的问题。只能说明是spring 4.0的新特性所致。于是开始跟踪源码,最后终于发现了“惊天大幂幂”。。。
Spring 2.0的配置
bean类:
package com.zm.bean;
import java.util.Date;
public class Bean1 {
private Date dateValue;
public Date getDateValue() {
return dateValue;
}
public void setDateValue(Date dateValue) {
this.dateValue = dateValue;
}
}
自定义属性编辑器类(UtilDatePropertyEditor):
package com.zm.bean;
import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
public class UtilDatePropertyEditor extends PropertyEditorSupport {
private String format="yyyy-MM-dd";
@Override
public void setAsText(String text) throws IllegalArgumentException {
// TODO Auto-generated method stub
System.out.println("UtilDatePropertyEditor.setAsText() -- text=" + text);
SimpleDateFormat sdf = new SimpleDateFormat(format);
try{
Date d = sdf.parse(text);
this.setValue(d);
}catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void setFormat(String format) {
this.format = format;
}
}
相关配置:
<span style="white-space:pre"> </span><!-- 配置bean1 -->
<bean id="bean1" class="com.zm.bean.Bean1">
<property name="dateValue" value="2016-08-20"/>
</bean>
<!-- 配置自定义属性编辑器 -->
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date" >
<bean class="com.zm.bean.UtilDatePropertyEditor">
<property name="format" value="yyyy-MM-dd"/>
</bean>
</entry>
</map>
</property>
</bean>
Spring 4.0的配置
相关配置:
<span style="white-space:pre"> </span><!-- 配置bean1 -->
<bean id="bean1" class="com.zm.bean.Bean1">
<property name="dateValue" value="2016-08-20"/>
</bean>
<!-- 配置自定义属性编辑器 -->
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date" value="com.zm.bean.UtilDatePropertyEditor"/>
</map>
</property>
</bean>
对比上面的配置可以发现,唯一的区别在于,在配置customEditors属性的时候,spring2.0配置的<entry>的value是一个<bean>,而spring4.0配置的<entry>的value是类名。
查看源码可以发现customEditors的类型,在spring2.0 中是Map类型,key和value的类型并不确定,但是底层处理的时候,key的类型必须是Class类型,而value是一个注入的bean;在spring4.0中,customEditors的类型变为了Map<Class<?>, Class<? extends PropertyEditor>>, 也就是说,key和value的类型已经确定为Class类型。