1. 程式人生 > >spring4.0之後,自定義屬性編輯器的配置變化

spring4.0之後,自定義屬性編輯器的配置變化

問題: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型別。