在Spring配置文件中,用户不单可以将int,String等字面值注入Bean中,还可以注入集合,List的类型,以及自定义类型;
接下来,我们一起进入Spring注入参数的学习!
1.设置内部Bean
如果book Bean只被author Bean 引用,不被容器中其他Bean引用,在这种情况下我们就可以将book 以内部Bean的方式注入到Bean中。先建一个Author类,在类中增加两个属性,name 和 book,其中Book类是自定义的类;为了方便学习,我们在两个属性的set方法中各写一条输出语句,以便之后控制台的查看;
Author.class
package com.vtstar.entity;
/**
* @ClassName Author
* @Description TODO
* @Author XiaoWu
* @Date 2018/9/6 14:40
* @Version 1.0
**/
public class Author {
private String name;
private Book book = new Book();
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("Author name:"+name);
this.name = name;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
System.out.println("我是内部Bean创建的Book 我的名字叫:" + book.getName() + " 价格为:" + book.getPrice());
this.book = book;
}
}
Book.class
package com.vtstar.entity;
/**
* @ClassName Book
* @Description TODO
* @Author XiaoWu
* @Date 2018/9/6 14:40
* @Version 1.0
**/
public class Book {
private String name;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("Book name:" + name);
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
System.out.println("Book price:" + price);
this.price = price;
}
}
定义内部Bean 和 声明Java中的匿名类相似,既没有名字,也不能被其他的Bean引用,只能在声明Bean的时候提供实例注入。在内部Bean中即使提供了id,name,scope属性,也会被忽略,scope默认为proptotype (非单例模式)。
<!--内部Bean-->
<bean id="author" class="com.vtstar.entity.Author">
<property name="book">
<bean class="com.vtstar.entity.Book">
<property name="price" value="22.0"/>
<property name="name" value="老人与海"/>
</bean>
</property>
</bean>
控制台输出:
2.设置null值
如果你想通过Spring容器在Book中的name里注入一个null值或者空字符串,你可以通过以下的配置来获取。
<!--设置null值-->
<bean id="author2" class="com.vtstar.entity.Author">
<property name="name"><value/></property><!--注入的是空字符串 -->
<property name="name"><null/></property><!--注入的是null -->
</bean>
<value/>打印结果:
<null/>等同于author.setName(null)。
3.级联属性
和Struts,Hibernate框架一样,Spring也支持级联属性的操作,如果你想在定义author时直接为book的属性提供注入值,可以采取如下配置方式:
<!--级联属性-->
<bean id="author3" class="com.vtstar.entity.Author">
<property name="book.name" value="三体"/>
<property name="book.price" value="33.9"/>
</bean>
值得一提的是在Author类中一定要实例化book类,不能只声明Book类,如果不实例化Book类,Spring容器不会允许你进行级联操作,就会抛出NullValueInNestedPathException异常;
所以为了程序能够正常启动,还是按照Spring的要求来办吧!
// private Book book; 错误的写法
private Book book = new Book();//正确的写法
控制台结果:
4.集合类型
接下来我们来注入list set map properties常用的数据结构类型;
新建一个ListType类,相关的集合属性已经在这个类中建好;
package com.vtstar.entity;
import java.util.*;
/**
* @ClassName ListType
* @Description java.util包下的集合类型是最常用的数据结构类型,其中包括 List Set Map Porperties
* @Author XiaoWu
* @Date 2018/9/6 15:06
* @Version 1.0
**/
public class ListType {
//list集合
private List favorites = new ArrayList();
public List getFavorites() {
return favorites;
}
public void setFavorites(List favorites) {
this.favorites = favorites;
for (Object list :favorites) {
System.out.println("list [] :"+list.toString());
}
}
//set集合
private Set favorites2 = new HashSet();
public Set getFavorites2() {
return favorites2;
}
public void setFavorites2(Set favorites2) {
this.favorites2 = favorites2;
for (Object set: favorites2 ) {
System.out.println("set [] :"+set.toString());
}
}
//map集合
private Map jobs = new HashMap();
public Map getJobs() {
return jobs;
}
public void setJobs(Map jobs) {
this.jobs = jobs;
for (Object job: jobs.keySet()) {
System.out.println("map key == " + job + " value == " + jobs.get(job).toString());
}
}
//properties集合
private Properties mails = new Properties();
public Properties getMails() {
return mails;
}
public void setMails(Properties mails) {
this.mails = mails;
for (String prop:mails.stringPropertyNames()) {
System.out.println("properties key == " + prop + " value == " + mails.getProperty(prop));
}
}
//强类型集合
private Map<String,Integer> jobTime = new HashMap<String, Integer>();
public Map<String, Integer> getJobTime() {
return jobTime;
}
public void setJobTime(Map<String, Integer> jobTime) {
this.jobTime = jobTime;
for (Map.Entry<String,Integer> job: jobTime.entrySet()) {
System.out.println("map<String,Integer> key == " + job.getKey() + " value == " + job.getValue());
}
}
//集合合并
private Set favorites3 = new HashSet();
public Set getFavorites3() {
return favorites3;
}
public void setFavorites3(Set favorites3) {
this.favorites3 = favorites3;
for (Object set: favorites3 ) {
System.out.println("merge set [] :"+set.toString());
}
}
}
1.List
Spring中配置List类型的favorites属性。
<!--1.list-->
<bean id="listType" class="com.vtstar.entity.ListType">
<property name="favorites">
<list>
<value>吃饭</value>
<value>睡觉</value>
<value>打豆豆</value>
</list>
</property>
</bean>
List属性既可以通过<value/>注入字符串,也可以通过<ref/>注入容器中其他的Bean。
控制台输出结果:
2.Set
<!--2.set-->
<bean id="setType" class="com.vtstar.entity.ListType">
<property name="favorites2">
<set>
<value>抽烟</value>
<value>喝酒</value>
<value>烫头</value>
</set>
</property>
</bean>
控制台输出结果:
3.Map
<bean id="boss" class="com.vtstar.entity.Boss">
<constructor-arg value="Tom"/>
<constructor-arg ref="car1"/>
<constructor-arg value="20"/>
</bean>
<bean id="car" class="com.vtstar.entity.Car">
<property name="brand" value="保时捷 k3TIM"/>
<property name="maxSpeed" value="100"/>
<property name="price" value="30.1"/>
</bean>
<!--3.map-->
<bean id="mapType" class="com.vtstar.entity.ListType">
<property name="jobs">
<map>
<entry>
<key><value>研发1</value></key>
<value>Java开发工程师</value>
</entry>
<entry>
<key><value>研发2</value></key>
<value>Php开发工程师</value>
</entry>
<entry>
<key><value>研发3</value></key>
<value>Ruby开发工程师</value>
</entry>
<!--如果map的key和value都是bean-->
<entry>
<key><ref bean="boss"/></key>
<ref bean="car"/>
</entry>
</map>
</property>
</bean>
map属性中的<entry/>表示Map中的一个元素,如果某个元素的键和值都是对象,则可以参考文中的最后一个entry;
控制台输出结果:
4.Properties
properties类型可以看做是Map类型的特例。map元素中的键和值可以是任何类型的对象,而properties属性的键和值都只能是字符串。
<!--4.properties-->
<bean id="propType" class="com.vtstar.entity.ListType">
<property name="mails">
<props>
<prop key="tomMail">vtstar-tom@smart.com</prop>
<prop key="jamesMail">vtstar-james@smart.com</prop>
</props>
</property>
</bean>
控制台打印结果:
5.强类型集合
<!--强类型集合-->
<bean id="bigMapType" class="com.vtstar.entity.ListType">
<property name="jobTime">
<map>
<entry>
<key><value>立春</value></key>
<value>119</value>
</entry>
<entry>
<key><value>立夏</value></key>
<value>320</value>
</entry>
<entry>
<key><value>立秋</value></key>
<value>626</value>
</entry>
<entry>
<key><value>立冬</value></key>
<value>930</value>
</entry>
</map>
</property>
</bean>
强类型集合在Spring中的配置和非强类型集合相同,但是Spring在注入强类型集合时会判断元素的类型,将设置值转换为对应的数据类型,如key在元素中的类型是String,value在元素中的类型是Integer。
控制台输出结果:
6.集合合并
Spring支持集合合并的功能,允许子Bean继承父Bean的同名属性集合元素,并将子Bean中配置的集合属性值和父Bean中配置的集合属性值合并起来成为最终Bean的属性值。就像两个A,B水果篮子,A篮子中有香蕉,苹果;B篮子中有柠檬,菠萝蜜;这时把A篮子中的成员放置到一个B篮子里面,就组成一个最终的水果篮子,但是前提必须都是水果。
<!--合并集合-->
<bean id="parentType" abstract="true" class="com.vtstar.entity.ListType">
<property name="favorites3">
<set>
<value>Java</value>
<value>.Net</value>
<value>Php</value>
</set>
</property>
</bean>
<bean id="childType" parent="parentType">
<property name="favorites3">
<set merge="true">
<value>Html</value>
<value>Javascript</value>
<value>jQuery</value>
</set>
</property>
</bean>
merge="true"属性指示子Bean和父Bean中的同名属性值进行合并,如果为false就不会进行合并;
控制台输出: