- Published on
Spring-Dependencies
- Authors
- Name
- Wenzhuo Zhao
A typical enterprise application does not consist of a single object (or bean in the Spring parlance). Even the simplest application has a few objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand alone to a fully realized application where objects collaborate to achieve a goal.
本篇文章介绍注入Bean的方式。
- 通过构造方式注入Bean
- 通过set方式注入Bean
- 集合类Bean的注入
- List
- Set
- Map
- Properties
- null值注入
- 注入时创建内部Bean
通过构造方式注入Bean
假设现在我们有两个类:Bean和AnotherBean,其中Bean依赖于AnotherBean
public class AnotherBean {
}
public class Bean {
private AnotherBean anotherBean;
private String text;
public Bean(AnotherBean anotherBean, String text){
this.anotherBean = anotherBean;
this.text = text;
}
@Override
public String toString() {
return "Bean{" +
"anotherBean=" + anotherBean +
", text='" + text + '\'' +
'}';
}
}
可以看到,在Bean的构造函数中,需要AnotherBean。如何在spring.xml中,配置这种Bean的注入呢?
首先不要忘记引入maven依赖:spring-core
, spring-context
和单元测试junit
。
然后在ressources下新建spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="AnotherBean" id="anotherBean"/>
</beans>
对AnotherBean,无须多言;对于Bean,我们需要使用<constructor>
标签来描述其构造函数。
public Bean(AnotherBean anotherBean, String text){
this.anotherBean = anotherBean;
this.text = text;
}
Bean的构造函数中,第一个参数类型为AnotherBean,名为anotherBean;第二个参数类型为java.lang.String,名为text,也就是我们有两个argument,在spring.xml中,添加如下Bean的配置:
<bean class="Bean" id="bean">
<constructor-arg index="0" name="anotherBean" type="AnotherBean" ref="anotherBean"/>
<constructor-arg index="1" name="text" type="java.lang.String" value="hello"/>
</bean>
index
: 参数的位置,0对应构造函数中第一个参数name
: 参数在构造函数中的名字type
: 参数的对象类型value
和ref
: 如果参数类型为Java自带的基本类型,则使用value
用来赋值。如果参数类型为自定义的,例如AnotherBean类型,则需要在spring.xml中定义,ref
指向定义的bean的id
接下来编写我们的测试代码
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Bean bean = context.getBean("bean",Bean.class);
System.out.println("bean = " + bean);
}
得到输出:
bean = Bean{anotherBean=AnotherBean@64f6106c, text='hello'}
能看到我们在spring.xml中设定的值已经成功注入了。
通过setter方式注入
在Bean的原基础上,增加两个属性来供我们实验。这两个属性,是不通过构造函数注入的。
private AnotherBean anotherBean1;
private String text1;
既然要用到setter方式注入,那就不可缺少setter方法。当然,toString方法也需要重写。
public AnotherBean getAnotherBean1() {
return anotherBean1;
}
public void setAnotherBean1(AnotherBean anotherBean1) {
this.anotherBean1 = anotherBean1;
}
public String getText1() {
return text1;
}
public void setText1(String text1) {
this.text1 = text1;
}
@Override
public String toString() {
return "Bean{" +
"anotherBean=" + anotherBean +
", text='" + text + '\'' +
", anotherBean1=" + anotherBean1 +
", text1='" + text1 + '\'' +
'}';
}
在spring.xml中,用<property>
标签来描述这两个属性。
<property name="anotherBean1" ref="anotherBean"/>
<property name="text1" value="world" />
name
: 属性的名字ref
或value
: 属性的值,与刚刚的相同。
测试代码无需改动,当然,测试输出的结果会有所改动。
bean = Bean{anotherBean=AnotherBean@4fb64261, text='hello', anotherBean1=AnotherBean@4fb64261, text1='world'}
可以看到"world"被注入进来了。
一种简便写法
在spring.xml中的 头 内,加入两个新的属性:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
可以看到,我加入了xmlns:c
和xmlns:p
,那么c代表constructor, p代表property。对于Bean,可以这样重新写:
<bean class="Bean" id="bean"
c:anotherBean-ref="anotherBean" c:text="hello"
p:anotherBean1-ref="anotherBean" p:text1="world"/>
与之前的意义是一样的。大家也可以在Intellij IDEA内自己试验一下,看IDE会提示什么。
集合类Bean的注入
在Bean.java新增几个集合类属性来供我们学习。
private List<String> stringList;
private List<AnotherBean> anotherBeanList;
private Set<String> stringSet;
private Set<AnotherBean> anotherBeanSet;
private Map<String, String> stringMap;
private Map<String, AnotherBean> anotherBeanMap;
private Properties properties;
还是用setter方法来注入,因此不要忘记他们的get和set方法,这里就不写了。
在spring.xml内,为我们的这些集合赋值。
<property name="stringList">
<list>
<value>first of list</value>
<value>second of list</value>
</list>
</property>
<property name="anotherBeanList">
<list>
<ref bean="anotherBean"/>
<ref bean="anotherBean" />
</list>
</property>
<property name="stringSet">
<set>
<value>a value of set</value>
<value>another value of set</value>
</set>
</property>
<property name="anotherBeanSet">
<set>
<ref bean="anotherBean" />
<ref bean="anotherBean" />
<!--实际上写一个就行,因为Set不允许重复元素-->
</set>
</property>
<property name="stringMap">
<map>
<entry key="firstString" value="first of map"/>
<entry key="secondString" value="second of map"/>
</map>
</property>
<property name="anotherBeanMap">
<map>
<entry key="firstBean" value-ref="anotherBean"/>
<entry key="secondBean" value-ref="anotherBean" />
</map>
</property>
<property name="properties">
<props>
<prop key="aProp">PROP</prop>
</props>
</property>
还是相同的,ref要指向配置文件中的Bean对象,value则不用。
前面的不动,测试结果为
bean = Bean{anotherBean=AnotherBean@8e24743,
text='hello',
anotherBean1=AnotherBean@8e24743,
text1='world',
stringList=[first of list, second of list],
anotherBeanList=[AnotherBean@8e24743, AnotherBean@8e24743],
stringSet=[a value of set, another value of set],
anotherBeanSet=[AnotherBean@8e24743],
stringMap={firstString=first of map,
secondString=second of map},
anotherBeanMap={firstBean=AnotherBean@8e24743, secondBean=AnotherBean@8e24743},
properties={aProp=PROP}}
null值注入
只需要在<property>
标签内,加入<null/>
<property name="anotherBean">
<null/>
</property>
那么这个属性的值也就是null。
注入时创建内部Bean
对于一个属性,类型为自定义的对象,我们通常这样写
<property name="anotherBean1" ref="anotherBean"/>
ref
指向在同一配置文件中定义过的Bean的id。但如果我们不想这样指定呢?可以在<property>
中新建一个Bean。
<property name="anotherBean1">
<bean class="AnotherBean"></bean>
</property>
当然,这样新建的类型为AnotherBean的Bean,和其他通过ref指向的AnotherBean,在内存中就不是同一个对象了。