装配Bean
定义表演者(Performer)接口,含有一个表演(Perform)方法:
package com.springinaction.springidol;
public interface Performer{
void perform() throws PerformanceException;
}
定义一个具体的表演者(杂技师Juggler):
package com.springinaction.springidol;
public class Juggler implements Performer{
private in beanBags = 3;
public Juggler(){
}
//抛豆袋子的数量,可通过构造器传入,若不传则为默认值
public Juggler(int beanBags){
this.beanBags = beanBags;
}
//表演抛豆袋子
public void perform() throws PerformanceException{
System.out.println("Juggling" + beanBags + "BEANBAGS");
}
}
在配置文件中定义该表演者:
<!-- 该表演者名为duke,职业为杂技师(Juggler) -->
<bean id="duke" class="com.springinaction.springidol.Juggler" />
通过构造器注入(豆子的数量):
<bean id="duke" class="com.springinaction.springidol.Juggler">
<constuctor-arg value="15" />
</bean>
但是duke不只是杂技师,他还是一位会朗诵诗歌的杂技师,所以需要定义一个新的继承自Juggler的PoeticJuggler类来全面展现duke的才能:
public class PoeticJuggler extends Juggler{
private Poem poem;
public PoeticJuggler(Poem poem){
sugar(beansBags);
this.poem = poem;
}
//定义Poem接口
public PoeticJuggler(int beanBags.Poem poem){
super(beanBags);
this.poem = poem;
}
public void perform() throws PerformanceException{
super.perform();
System.out.println("While reciting...");
poem.recite();
}
}
定义朗诵诗歌接口:
package com.springinaction.springidol;
public interface Poem{
void recite();
}
表演朗诵诗歌的类:
package com.springinaction.springidol;
public class Sonnet29 implements Poem{
private static String[] LINES = {
"诗句第一行",
"诗句第二行",
"诗句第三行",
"诗句第四行",
"诗句第五行",
"诗句第六行",
"诗句第七行",
"诗句第八行",
"诗句第九行"};
public Sonnet29(){
}
public void recite(){
for(int i = 0;i<LINES.length;i++){
System.out.println(LINES[i]);
}
}
}
声明表演诗歌的类:
<bean id="sonnet29" class="com.springinaction.springidol.sonnet29" />
将poem赋予Duke(调用PoeticJuggler有两个参数的构造器):
<bean id="poeticDuke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<constructor-arg ref="sonnet29" />
</bean>
<constructor-arg ref="sonnet29" />将id为sonnet29的bean当作引用传给PoeticJuggler的构造器。
通过工厂方法创建Bean
单例(舞台)类:
package com.springinaction.springidol;
public class Stage{
//只有一个私有构造器,无法通过new创建Stage实例
pvivate Stage(){
}
//延迟加载实例
private static class StageSingletonHolder{
static Stage instance = new Stage();
}
//返时实例
public static Stage getInstance(){
return StageSingletonHolder.instance;
}
}
在Spring中,factory-method属性允许调用一个指定的静态方法,从而代替构造方法来创建一个类的实例,将没有公开构造方法的类配置为一个Bean:
<bean id="theStage" class="com.springinaction.springidol.Stage" factory-method="getInstance" />
2.1.4 Bean的作用域
当在Spring中配置<bean>元素时,可以为Bean声明一个作用域。为了让Spring在每次请求时都为Bean产生一个新的实例,只需要配置Bean的scope属性为prototype即可。例如,把演出门票声明为Spring bean:
<bean id="ticket" class="com.springinaction.springidol.Ticket" scope="prototype" />
以保证每个观看演出的人手里的票绝对唯一。
作用域表:
作用域 | 定义 |
---|---|
singleton | 在每一个Spring容器中,一个Bean定义只有一个对象实例(默认) |
prototype | 允许Bean的定义可以被实例化任意次(每次调用都创建一个实例) |
request | 在一次HTTP请求中,每个Bean定义对应一个实例。该作用域仅在基于web的Spring上下文(例如Spring MVC中才有效) |
session | 在一个HTTP Session中,每个Bean定义对应一个实例。该作用域仅在基于web的Spring上下文(例如Spring MVC中才有效) |
global-session | 在一个全局HTTP Session中,每个Bean定义对应一个实例。该作用域尽在Portlet上下文中才有效。 |
2.1.5 初始化和销毁Bean
表演大厅(Auditorium)类:
public class Auditorium{
//表演开始时开灯
public void turnOnLights(){
...
}
//表演结束时关灯
public void turnOffLights(){
}
}
在配置文件中定义Bean时,使用init-method方法和destroy-method方法指定初始化bean和销毁bean时要调用的方法:
<bean id="auditorium"
class="com.springinaction.springidol.Auditorium"
init-method="turnOnLights"
destroy-method="turnOffLights" />
2.2 注入Bean属性
package com.springinaction.springidol;
public class Instrumentalist implements Performer{
public Instrumentalist (){
}
public void perform() throws PerformancException{
System.out.println("Playing" + song + " : ");
instrument.play();
}
//定义歌曲名字
private String song;
//注入歌曲
public void setSong(String song){
this.song = song;
}
public String getSong(){
return song;
}
public String screamSong(){
return song;
}
private Instrument instrument;
//注入乐器
public void setInstrument(Instrument instrument){
this.instrument = instrument;
}
}
乐器接口:
package com.springinaction.springidol;
public interface instrument{
public void play();
}
实现了乐器接口的saxophone乐器类:
package com.springinaction.springidol;
public class Saxophone implements Instrument{
public Saxophone{
}
public void play(){
System.out.println("TOOT TOOT TOOT");
}
}
在配置中声明Saxophone对应的Bean:
<bean id="saxophone" class="com.springinaction.springidol.Saxophone" />
配置(将Jinggle Bells这首歌和Saxophone乐器的引用注入到名为kenny的音乐演奏家instrument类对应的属性中):
<bean id="kenny" class=com.springinaction.springidol.Instrumentalist">
<property name ="song" value="Jingle Bells" />
<property name="instrument" ref="saxophone"
</bean>
注入内部Bean:
<bean id="kenny" class=com.springinaction.springidol.Instrumentalist">
<property name ="song" value="Jingle Bells" />
<property name="instrument">
<bean class="org.springinaction.springidol.Saxophone" />
</property>
</bean>
也可以将内部Bean装配到构造方法的入参中:
<bean id="duke" class=com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<constructor-arg>
<bean class="com.springinaction.springidol.Sonnet29" />
</constructor-arg>
</bean>
内部Bean没有ID属性,虽然可以但没有必要,因为永远不会通过名字来引用内部Bean。内部Bean不能被复用,仅用于一次注入,而且也不能被其他Bean引用。
装配集合属性:
集合元素 | 用途 |
<list> | 装配list类型的值,允许重复 |
<set> | 装配set类型的值,不允许重复 |
<map> | 装配map类型的值,名称和值可以是任意类型 |
<props> | 装配properties类型的值,名称和值必须都是String型 |
package com.springinaction.springidol;
import java.util.Collection;
public class OneManBand implements Performer{
public OneManBand(){
}
public void perform() throws PerformanceException{
for (Instrument instrument : instruments){
instrument.play();
}
}
private Collection<Instrument> instruments;
public void setInstruments(Collection<Instrument> instruments){
//注入instrument集合
this.instruments = instruments;
}
}
装配List