以下是个模拟的例子,java类来参加一个叫Spring Idol的比赛节目,来找出表演最好的Java类,这里的类都集成下面的接口
package
com.springinaction.springidol;
public
interface
Performer {
void
perform()
throws
PerformanceException;
}
在这个比赛里,你会看到几个参与者,每个都实现上面的接口,先看第一个,使用的是
spring
的构造器注入。
2.2.1声明一个bean
第一个类是Juggler,跟其他的比赛节目不同,这可不是唱歌。例如,其中一个performer是一个Juggler(魔术师?),魔术师类声明如下:
package
com.springinaction.springidol;
public
class
Juggler
implements
Performer {
private
int
beanBags
= 3;
public
Juggler(){}
public
Juggler(
int
beanBags){
this
.
beanBags
= beanBags;
}
public
void
perform()
throws
PerformanceException{
System.
out
.println(
"JUGGLING "
+
beanBags
+
" BEANBAGS"
);
}
}
那么现在第一个参与者出现了,在
xml
定义文件中(
springidol.xml
)中我们这样声明:
<
bean
id
=
"duke"
class
=
"com.springinaction.springidol.Juggler"
/>
Bean元素是spring中配置的最基本的单元,它告诉spring创建一个对象。这里创建的是一个叫duke的由spring容器管理的bean,这是最简单的声明。id给出了向容器申请的名称。那么这个bean就叫做duke,同时,class属性指明了他是个Juggler。
当spring容器载入它里面声明的bean时,它会用duke bean的默认构造器。基本上(实际上,是通过reflection),duke的初始化是下面的代码:
new com.springinaction.springidol.Juggler();
可以给duke一个机会参加这个比赛,Spring ApplicationContext用下面的代码
ApplicationContext context = new ClassPathXmlApplicationContext(“springidol.xml”);
Performer performer = (Performer)context.getBean(“duke”);
performer.performer();
尽管这不是真正的比赛,运行代码,你会得到下面的输出:
JUGGLING 3 BEANBAGS
默认的,duke一次juggle了3个beanbags。但一次juggle3个beanbag不是什么难事,每个人都可以。如果duke想赢得比赛,他需要juggle更多的beanbag。让我们看看duke如何成为冠军。
2.2.2构造器注入
为了给评委留下印象,duke决定一次性juggle15个beanbag,创个世界纪录②。
从Juggler的代码中可以看到,它提供了2个构造器,可以用2种方法来初始化。
尽管上节声明的duke可以用,它使用了默认的构造器,这样限制了duke只能一次juggle3个beanbag,如果变成15的话,那只能使用另外一个构造器。下面就是xml配置的代码
<
bean
id
=
"duke"
class
=
"com.springinaction.springidol.Juggler"
>
<
constructor-arg
value
=
"15"
></
constructor-arg
>
</
bean
>
Constructor-arg是在创建bean时用来告诉spring更多信息的元素。如果没有这个元素,那么就是用默认的构造器,现在给出了,就用另外一个了。
现在执行duke,输出变了:
JUGGLING 15 BEANBAGS
一次juggle15个可能不够吸引人。但关于duke你还有不知道的,他不仅是个好的juggler,而且他还很会背诵诗歌。变魔术时还能背诗会是个不错的想法。
通过构造器来注入对象
因为duke是个魔术师,而且是个背诗的魔术师,那就要换个类型了。PoeticJuggler描述duke更好。
package com.springinaction.springidol;
public class PoeticJuggler extends Juggler{
private Poem poem;
public PoeticJuggler(Poem poem){
super();
this.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 {
public void recite();
}
Duke最喜欢的诗是:“!@#%#%¥#……¥!!@##%#@!#@!#@!”,Sonnet29实现了接口Poem。
package com.springinaction.springidol;
public class Sonnet29 implements Poem {
private static String[]lines ={" dfjuaogfwofdlaf ",
" fdafwoafjodajfo ",
" djsavfojwoqpvjos "};
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了。现在duke是个PoeticJuggler,他的bean定义要修改一下
<bean id="duke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15"></constructor-arg>
<constructor-arg ref="sonnet29"/>
</bean>
PoemticJuggler没有默认的构造器,所以只能通过参数传递进去。这个例子中,我们把一个int和一个Poem类型的参数传递给构造器。Duke的bean声明也提供15这个int放入constructor-arg里面。
但poem不能简单赋值,因此,ref是用来指定实例的。尽管还有更多的细节,你可以想想现在的过程就是下面的代码
Poem sonnet29 = new Sonnet29();
Performer duke = new PoemticJuggler(15,sonnet29);
构造器和setter方法的注入,我们到底选哪个?page80
现在执行duke,他就可以变魔术和背诗了。输出如下:
JUGGLING 15 BEANBAGS
WHILE RECITING…
Dfjuaogfwofdlaf
………
构造器注入一定会保证bean在使用前配置好了。但它自己不会进行复杂的配置,幸运的是,Spring不限制你使用哪个方法,你可以随意使用构造器和setter方法注入。下面看setter注入。