一般来说,JavaBean的字段是私有的,带有一组存取器方法(setXXX()和getXXX())
Spring借助字段的的set方法来配置字段,以实现setter方式的注入。
示例:继上文,Idol秀来了一位有天赋的的音乐演奏参赛者,该表演参赛者实现了表演接口。
package com.li.spring.chineseidol;
import java.io.File;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*音乐演奏者*/
public class Instrumentalist implements Performer {
private String song; //表演者所唱的歌曲
private Instrument instrument; //一个接口,表演者所使用的乐器
public Instrumentalist() {}
@Override
public void perform() throws PerformanceException {
System.out.println("Playing "+song+":");
instrument.play();
}
public void setSong(String song) {
this.song=song;
}
public String getSong() {
return song;
}
public Instrument getInstrument() {
return instrument;
}
public void setInstrument(Instrument instrument) {
this.instrument = instrument;
}
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("com"+File.separator+"li"+File.separator+"spring"+File.separator+"chineseidol"+File.separator+"chinese-idol.xml");
Performer performer=(Performer) ctx.getBean("instrumentalist");
try {
performer.perform();
} catch (PerformanceException e) {
e.printStackTrace();
}
}
}
其中,乐器接口定义了一个play()表示演奏的方法:
package com.li.spring.chineseidol;
/*乐器接口*/
public interface Instrument {
void play();
}
Spring可以使用
<bean id="instrumentalist" class="com.li.spring.chineseidol.Instrumentalist">
<property name="song" value="memory">property>
bean>
一旦Instrumentalist被实例化,Spring就会调用
因为上面的类中还有一个成员变量,是一个乐器接口,因此我们还需要注入乐器接口的实现类Bean。那么首先,创建一个乐器接口的实现类:
package com.li.spring.chineseidol;
public class Saxophone implements Instrument {
public Saxophone() {}
@Override
public void play() {
System.out.println("嘟嘟嘟,开车了!");
}
}
然后配置Bean并将它注入到 “instrumentalist” Bean中去,同样使用的是property元素,但是引用其他的Bean使用了ref属性,ref属性的值是Bean的id。
<bean id="instrumentalist" class="com.li.spring.chineseidol.Instrumentalist">
<property name="song" value="memory">property>
<property name="instrument" ref="saxophone">property>
bean>
<bean id="saxophone" class="com.li.spring.chineseidol.Saxophone">bean>
这时我们可以运行一下上面的程序了:
Playing memory:
嘟嘟嘟,开车了!
请注意,我们为什么在 Instrumentalist 类中,成员变量使用乐器接口(Instrument)而不是使用其具体实现类(比如Saxophone)呢?实际上这就是针对接口编程,接口定义了一系列行为,而实现类确定了行为的具体实现。针对接口编程与依赖注入协作实现松散耦合。例如:
我们还有另一种乐器,也是实现类乐器接口:
package com.li.spring.chineseidol;
public class Piano implements Instrument {
@Override
public void play() {
System.out.println("铛 铛 铛!");
}
}
我们也可以配置此Bean并为乐器表演者注入此Bean,这样我们无需修改类的结构,这就是针对接口编程的好处:
<bean id="instrumentalist" class="com.li.spring.chineseidol.Instrumentalist">
<property name="song" value="memory">property>
<property name="instrument" ref="piano">property>
bean>
<bean id="piano" class="com.li.spring.chineseidol.Piano">bean>
Spring的命名空间p提供了另一种Bean属性的装配方式,要使用命名空间p,需要在Spring的XML配置文件中增加一段声明:
需要增加的声明:
xmlns:p="http://www.springframework.org/schema/p
Spring的XML配置声明:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
beans>
改写前面的示例:
<bean id="instrumentalist" class="com.li.spring.chineseidol.Instrumentalist"
p:song="memory"
p:instrument-ref="saxophone"/>
当配置集合类型的Bean属性时,Spring提供了四种类型的集合配置元素:
collection element | useful for… |
---|---|
wiring list of values, allowing duplicates | |
wiring set of values, ensuring no duplicates | |
wiring a collection of name-value pairs where name and value can be of any type | |
wiring a collection of name-value pairs where name and value are both strings |
- 当属性为任意的java.util.Collection类型时,和
示例:现在来了一位全能型的音乐演奏者,能演奏多种乐器,也实现了Performer接口
package com.li.spring.chineseidol;
import java.io.File;
import java.util.Collection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*全能型音乐演奏者,能演奏多种乐器*/
public class SuperInstrumentalist implements Performer {
/*能演奏乐器的集合*/
private Collection instruments;
@Override
public void perform() throws PerformanceException {
for(Instrument instrument : instruments)
instrument.play();
}
public Collection getInstruments() {
return instruments;
}
public void setInstruments(Collection instruments) {
this.instruments = instruments;
}
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("com"+File.separator+"li"+File.separator+"spring"+File.separator+"chineseidol"+File.separator+"chinese-idol.xml");
Performer performer=(Performer) ctx.getBean("superinstrument");
try {
performer.perform();
} catch (PerformanceException e) {
e.printStackTrace();
}
}
}
示例装配,使用的是list,这里也可以换成set:
<bean id="saxophone" class="com.li.spring.chineseidol.Saxophone">bean>
<bean id="piano" class="com.li.spring.chineseidol.Piano">bean>
<bean id="superinstrument" class="com.li.spring.chineseidol.SuperInstrumentalist">
<property name="instruments">
<list>
<ref bean="saxophone"/>
<ref bean="piano"/>
list>
property>
bean>
在上面的配置文件中,使用 property 元素的子元素——list来表示Collection集合的装配,其中ref元素表示引用,bean属性的值,是引用的Bean的id。
现在我们再稍微改一下,使用Map:
package com.li.spring.chineseidol;
import java.io.File;
import java.util.Collection;
import java.util.Map;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*全能型音乐演奏者,能演奏多种乐器*/
public class SuperInstrumentalist implements Performer {
private Map instruments;
@Override
public void perform() throws PerformanceException {
for(String key : instruments.keySet()) {
System.out.print(key+" : ");
Instrument instrument = instruments.get(key);
instrument.play();
}
}
public Map getInstruments() {
return instruments;
}
public void setInstruments(Map instruments) {
this.instruments = instruments;
}
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("com"+File.separator+"li"+File.separator+"spring"+File.separator+"chineseidol"+File.separator+"chinese-idol.xml");
Performer performer=(Performer) ctx.getBean("superinstrument");
try {
performer.perform();
} catch (PerformanceException e) {
e.printStackTrace();
}
}
}
示例装配,使用map:
<bean id="saxophone" class="com.li.spring.chineseidol.Saxophone">bean>
<bean id="piano" class="com.li.spring.chineseidol.Piano">bean>
<bean id="superinstrument" class="com.li.spring.chineseidol.SuperInstrumentalist">
<property name="instruments">
<map>
<entry key="piano" value-ref="piano">entry>
<entry key="saxophone" value-ref="saxophone">entry>
map>
property>
bean>
在上面的配置文件中,使用的是 property 元素的子元素 map 来表示 map集合的装配,其中,entity元素表示Map的键值对,这里key属性(或value属性)可以指定字符串(也可以是数值类型),而使用key-ref(或value-ref)则可以指定引用Bean的id。
Spring可以为Bean的属性或者构造器参数装配null值。
<property name="someNonNullProperty"><null/>property>
理由:需要显示的设置为null值,或者覆盖自动装配的值。