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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"><bean id="userDaoImp4MySql" ref="userDaoImp4Oracle"/></bean><bean id="upperAction" value="good"/></bean><bean id="lowerAction" 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 hierarchy2010-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@184ec442010-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 hierarchyzhangdong:23list1list2testCaseName:testSpringtestCaseName1:testSpring1set1set2[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" name="code">/* * 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 value="mypackage.MyCustomDateEditor"/> * <entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/> * </map> * </property> * </bean></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-Orderedprivate 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" 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" 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");
?
引用[color=red][/color][size=xx-small][/size][align=left][/align]