`

Spring Set注入:基本类型、List、Map、Set、Array、Date类型注入

阅读更多

Spring依赖注入有两种:构造器注入与Set注入

其中以Set注入为首选。下面演示几个示例。

Bean类:User

package com.lwf.bean;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class User {

	private String name;
	private int age;
	private List listValues;
	
	private Map map ;
	private Set set;
	private String [] array;
	private Date date;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public List getListValues() {
		return listValues;
	}
	public void setListValues(List listValues) {
		this.listValues = listValues;
	}
	public Map getMap() {
		return map;
	}
	public void setMap(Map map) {
		this.map = map;
	}
	public Set getSet() {
		return set;
	}
	public void setSet(Set set) {
		this.set = set;
	}
	public String[] getArray() {
		return array;
	}
	public void setArray(String[] array) {
		this.array = array;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
}

 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">


	
	<bean id="userDaoImp4MySql" class="com.lwf.dao.UserDaoImp4MySql"/>
	<bean id="userDaoImp4Oracle" class="com.lwf.dao.UserDaoImp4Oracle"/>
	<bean id="userManager" class="com.lwf.manager.UserManagerImp">
		<property name="userDao" ref="userDaoImp4Oracle"/>
	</bean>


	<bean id="upperAction" class="com.lwf.action.UpperAction">
		<property name="message" value="good"/>
	</bean>
	<bean id="lowerAction" class="com.lwf.action.LowerAction"/>
	
	<bean id="user" class="com.lwf.bean.User">
		<property name="name"><value>zhangdong</value></property>
		<property name="age" value="23" />
		<property name="listValues">
			<list>
				<value>list1</value>
				<value>list2</value>
			</list>
		</property>
		<property name="array">
			<list>
				<value>array1</value>
				<value>array2</value>
			</list>
		</property>
		<property name="map">
			<map>
				<entry>
					<key ><value>testCaseName</value></key>
					<value>testSpring</value>
				</entry>
				<entry>
					<key ><value>testCaseName1</value></key>
					<value>testSpring1</value>
				</entry>
			</map>
		</property>
		<property name="set">
			<set>
				<value>set1</value>
				<value>set2</value>
			</set>
		</property>
		
	</bean>
	
	
</beans>

 测试类:

package com.lwf.client;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.lwf.bean.User;

public class Client {
	public static void main(String[] args) {
	ApplicationContext ctx2 = new FileSystemXmlApplicationContext("/src/applicationContext.xml");
		User user = (User)ctx2.getBean("user");
		System.out.println(user.getName() +":"+ user.getAge());
		List list = user.getListValues();
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
			
		}
		
		Map map = user.getMap();
		for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
			Map.Entry object = (Map.Entry) iter.next();
			System.out.println((String)object.getKey() +":"+ (String)object.getValue());
			
		}
		
		Set set = user.getSet();
		for(Iterator iter = set.iterator();iter.hasNext();){
			String str = (String)iter.next();
			System.out.println(str);
		}
		
		String[] array = user.getArray();
		System.out.println(array);
		
	}
}

 

说明:上例测试了普通属性的注入,List,Map,Array,Set属性的注入。

测试打印出内容:

2010-05-18 15:56:16,794 INFO [org.springframework.context.support.FileSystemXmlApplicationContext] - Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@3e86d0: display name [org.springframework.context.support.FileSystemXmlApplicationContext@3e86d0]; startup date [Tue May 18 15:56:16 CST 2010]; root of context hierarchy
2010-05-18 15:56:16,997 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from file [D:\workdirlocal\spring_start\src\applicationContext.xml]
2010-05-18 15:56:17,388 INFO [org.springframework.context.support.FileSystemXmlApplicationContext] - Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext@3e86d0]: org.springframework.beans.factory.support.DefaultListableBeanFactory@184ec44
2010-05-18 15:56:17,450 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@184ec44: defining beans [userDaoImp4MySql,userDaoImp4Oracle,userManager,upperAction,lowerAction,user]; root of factory hierarchy
zhangdong:23
list1
list2
testCaseName:testSpring
testCaseName1:testSpring1
set1
set2
[Ljava.lang.String;@1d6776d

 

好,我们的User类中定义了Date date,现在测试Date类型,现在在applicationContext.xml中加入:

<property name="date" value="2010/05/18"></property>

 

在测试类中加入:

System.out.println(user.getDate());

 

测试结果:

我们会发现报错:

Caused by: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'date'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property 'date': no matching editors or conversion strategy found

 

显然从字符串类型转换为Date类型出错,那么怎么办?

回忆一下Struts中actionForm怎么处理类型转换问题?

http://quicker.iteye.com/admin/blogs/629603

 在spring中。我们采取类似的思路,先自己创建转换器再注册。

转换器继承于java.bean.下面的类:

package com.lwf.bean;

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class UtilDatePropertiesEditor extends PropertyEditorSupport {

	private String format ;
	public void setAsText(String text) throws IllegalArgumentException {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			Date dateVal = sdf.parse(text);
			this.setValue(dateVal);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
	}
	
	public void setFormat(String format){
		this.format = format;
	}

}

 那么怎么注册呢?

我们先看在applicationContext.xml中加入

<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
		
	</bean>

 

按F3查找类org.springframework.beans.factory.config.CustomEditorConfigurer,定位spring源代码到src目录,即可看到CustomEditorConfigurer类的源码

/*
 * Copyright 2002-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import java.beans.PropertyEditor;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.core.Ordered;
import org.springframework.util.ClassUtils;

/**
 * {@link BeanFactoryPostProcessor} implementation that allows for convenient
 * registration of custom {@link PropertyEditor property editors}.
 *
 * <p>As of Spring 2.0, the recommended usage is to use custom
 * {@link PropertyEditorRegistrar} implementations that in turn register
 * any desired editors on a given
 * {@link org.springframework.beans.PropertyEditorRegistry registry}.
 * Each PropertyEditorRegistrar can register any number of custom editors.
 *
 * <pre class="code">
 * &lt;bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt;
 *   &lt;property name="propertyEditorRegistrars"&gt;
 *     &lt;list&gt;
 *       &lt;bean class="mypackage.MyCustomDateEditorRegistrar"/&gt;
 *       &lt;bean class="mypackage.MyObjectEditorRegistrar"/&gt;
 *     &lt;/list&gt;
 *   &lt;/property&gt;
 * &lt;/bean&gt;</pre>
 *
 * <p>Alternative configuration example with custom editor classes:
 *
 * <pre class="code">
 * &lt;bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt;
 *   &lt;property name="customEditors"&gt;
 *     &lt;map&gt;
 *       &lt;entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/&gt;
 *       &lt;entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/&gt;
 *     &lt;/map&gt;
 *   &lt;/property&gt;
 * &lt;/bean&gt;</pre>
 *
 * <p>Also supports "java.lang.String[]"-style array class names and primitive
 * class names (e.g. "boolean"). Delegates to {@link ClassUtils} for actual
 * class name resolution.
 *
 * <p><b>NOTE:</b> Custom property editors registered with this configurer do
 * <i>not</i> apply to data binding. Custom editors for data binding need to
 * be registered on the {@link org.springframework.validation.DataBinder}:
 * Use a common base class or delegate to common PropertyEditorRegistrar
 * implementations to reuse editor registration there.
 *
 * @author Juergen Hoeller
 * @since 27.02.2004
 * @see java.beans.PropertyEditor
 * @see org.springframework.beans.PropertyEditorRegistrar
 * @see ConfigurableBeanFactory#addPropertyEditorRegistrar
 * @see ConfigurableBeanFactory#registerCustomEditor
 * @see org.springframework.validation.DataBinder#registerCustomEditor
 * @see org.springframework.web.servlet.mvc.BaseCommandController#setPropertyEditorRegistrars
 * @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder
 */
public class CustomEditorConfigurer implements BeanFactoryPostProcessor, BeanClassLoaderAware, Ordered {

	protected final Log logger = LogFactory.getLog(getClass());

	private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered

	private PropertyEditorRegistrar[] propertyEditorRegistrars;

	private Map customEditors;

	private boolean ignoreUnresolvableEditors = false;

	private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();


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

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

	/**
	 * Specify the {@link PropertyEditorRegistrar PropertyEditorRegistrars}
	 * to apply to beans defined within the current application context.
	 * <p>This allows for sharing <code>PropertyEditorRegistrars</code> with
	 * {@link org.springframework.validation.DataBinder DataBinders}, etc.
	 * Furthermore, it avoids the need for synchronization on custom editors:
	 * A <code>PropertyEditorRegistrar</code> will always create fresh editor
	 * instances for each bean creation attempt.
	 * @see ConfigurableListableBeanFactory#addPropertyEditorRegistrar
	 */
	public void setPropertyEditorRegistrars(PropertyEditorRegistrar[] propertyEditorRegistrars) {
		this.propertyEditorRegistrars = propertyEditorRegistrars;
	}

	/**
	 * Specify the custom editors to register via a {@link Map}, using the
	 * class name of the required type as the key and the class name of the
	 * associated {@link PropertyEditor} as value.
	 * <p>Also supports {@link PropertyEditor} instances as values; however,
	 * this is deprecated since Spring 2.0.7 and will be removed in Spring 3.0.
	 * @param customEditors said <code>Map</code> of editors (can be <code>null</code>) 
	 * @see ConfigurableListableBeanFactory#registerCustomEditor
	 */
	public void setCustomEditors(Map customEditors) {
		this.customEditors = customEditors;
	}

	/**
	 * Set whether unresolvable editors should simply be skipped.
	 * Default is to raise an exception in such a case.
	 * <p>This typically applies to either the editor class or the required type
	 * class not being found in the classpath. If you expect this to happen in
	 * some deployments and prefer to simply ignore the affected editors,
	 * then switch this flag to "true".
	 */
	public void setIgnoreUnresolvableEditors(boolean ignoreUnresolvableEditors) {
		this.ignoreUnresolvableEditors = ignoreUnresolvableEditors;
	}

	public void setBeanClassLoader(ClassLoader beanClassLoader) {
		this.beanClassLoader = beanClassLoader;
	}


	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		if (this.propertyEditorRegistrars != null) {
			for (int i = 0; i < this.propertyEditorRegistrars.length; i++) {
				beanFactory.addPropertyEditorRegistrar(this.propertyEditorRegistrars[i]);
			}
		}

		if (this.customEditors != null) {
			for (Iterator it = this.customEditors.entrySet().iterator(); it.hasNext();) {
				Map.Entry entry = (Map.Entry) it.next();
				Object key = entry.getKey();
				Object value = entry.getValue();
				Class requiredType = null;

				try {
					if (key instanceof Class) {
						requiredType = (Class) key;
					}
					else if (key instanceof String) {
						requiredType = ClassUtils.forName((String) key, this.beanClassLoader);
					}
					else {
						throw new IllegalArgumentException(
								"Invalid key [" + key + "] for custom editor: needs to be Class or String.");
					}

					if (value instanceof PropertyEditor) {
						beanFactory.registerCustomEditor(requiredType, (PropertyEditor) value);
					}
					else if (value instanceof Class) {
						beanFactory.registerCustomEditor(requiredType, (Class) value);
					}
					else if (value instanceof String) {
						Class editorClass = ClassUtils.forName((String) value, this.beanClassLoader);
						beanFactory.registerCustomEditor(requiredType, editorClass);
					}
					else {
						throw new IllegalArgumentException("Mapped value [" + value + "] for custom editor key [" +
								key + "] is not of required type [" + PropertyEditor.class.getName() +
								"] or a corresponding Class or String value indicating a PropertyEditor implementation");
					}
				}
				catch (ClassNotFoundException ex) {
					if (this.ignoreUnresolvableEditors) {
						logger.info("Skipping editor [" + value + "] for required type [" + key + "]: " +
								(requiredType != null ? "editor" : "required type") + " class not found.");
					}
					else {
						throw new FatalBeanException(
								(requiredType != null ? "Editor" : "Required type") + " class not found", ex);
					}
				}
			}
		}
	}

}

 

我们可以看前面注释部分其实已经告诉我们怎么做了。

就是注入customEditors属性,注意看源代码customEditors属性是一个Map。

那么在applicationContext.xml前面加入:

<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
		<property name="customEditors">
			<map>
				<entry key="java.util.Date">
					<bean class="com.lwf.bean.UtilDatePropertiesEditor">
						<property name="format" value="yyyy/MM/dd"/>
					</bean>
				</entry>
			</map>
		</property>
	</bean>

 

注意在注册的同时,我们为UtilDatePropertiesEditor注入了format属性,这个属性可以指定格式。

后面仍然保持代码:

<property name="date" value="2010/05/18"></property>

 测试类代码中打印:System.out.println(user.getDate());

输出为:

Tue May 18 00:00:00 CST 2010

 

好了,现在我想改变格式如改成:2010-05-19。即

<property name="date" value="2010-05-19"></property>

那么顺便修改

 

   <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
     	<property name="customEditors">
     		<map>
     			<entry key="java.util.Date">
     				<bean class="com.bjsxt.spring.UtilDatePropertyEditor">
     					<property name="format" value="yyyy-MM-dd"/>
     				</bean>
     			</entry>
     		</map>
     	</property>
     </bean>

 那么打印日期输出:

Wed May 19 00:00:00 CST 2010

 

说明我们的日期转换并注册成功。

 

以上可得:

什么是属性编辑器,其作用?
    * 自定义属性编辑器,是将spring配置文件中的字符串转换成相应的对象进行注入,spring已经内置了很多类型
    的编辑器,我们可以自定义自己的属性编辑器
    
如何自定义属性编辑器?
	* 继承PropertyEditorSupport,覆写如下方法(参见UtilDatePropertyEditor.java):
	public void setAsText(String text) throws IllegalArgumentException
	
	* 将属性编辑器注册到spring中,参考:applicationContext.xml

 

对于配置文件有多个,并且名称相似如:

applicationContext-beans.xml

applicationContext-others.xml

那么我们在实例化容器的时候可以这样:

BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext-*.xml");
		
User user = (User)factory.getBean("user");

 

分享到:
评论
1 楼 youyou0248 2011-08-25  
[u][/u]

    [*]
[img][/img][url][/url][flash=200,200][/flash]
引用
[color=red][/color][size=xx-small][/size][align=left][/align]

相关推荐

Global site tag (gtag.js) - Google Analytics