第二章 bean捆绑基础(3节)

 
2.3 setter注入bean的属性
典型的, bean 提供一对函数用来访问属性的: setXXX() getXXX() Spring 利用这点进行 setter 注入。
为了实力 Spring 其它方式的 DI ,下面是另外一个 performer Kenny 是个不错的演奏家,定义如下:
package com.springinaction.springidol;
 
public interface Instrument {
    void play();
}
package com.springinaction.springidol;
 
public class Instrumentalist implements Performer {
    private String song ;
    private Instrument instrument ;
   
    public Instrumentalist(){}
   
    public void perform() throws PerformanceException {
       System. out .println( "Playing " + song + " : " );
       instrument .play();
    }
 
    public String getSong() {
       return song ;
    }
    public void setSong(String song) {
       this . song = song;
    }
 
    public Instrument getInstrument() {
       return instrument ;
    }
    public void setInstrument(Instrument instrument) {
       this . instrument = instrument;
    }
}
Kenny 可以在 bean 元素中进行如下定义:
< bean id = "kenny" class = "com.springinaction.springidol.Instrumentalist" >
</ bean >
尽管这样 kenny 就定义好了, 但是没有 song instrument kenny 是无法演奏的。下面介绍如何通过 setter 方法来注入。
2.3.1注入简单的数值
Bean 的属性可以通过 spring 中的 property 元素来进行配置, property constructor-arg 有很多类似的地方。除了一个是通过构造器,一个通过 setter 方法。
下面看看怎么进行注入
< bean id = "kenny" class = "com.springinaction.springidol.Instrumentalist" >
    < property name = "song" value = "Jingle Bells" />
</ bean >
一旦 Instrumentalist 被初始化, Spring setter 方法把 <property> 里面设置的值注入到对象中。这个例子把 Jingle Bells 放入到 kenny song 属性中。同一下的代码类似:
Instrumentalist Kenny = new Instrumentalist();
kenny.setSong(“Jingle Bells”);
但这个同 spring 配置生成有最重要的不同,就是 spring 提供了代码的松耦合, spring 的方法更灵活。
song 的属性这个例子中, <property> 注入了一个 String 的类型的值,不过 <property> 还可以注入别的类型, int float boolean java.lang.Double 等等 .
看下面配置:
    < bean id = "kenny" class = "com.springinaction.springidol.Instrumentalist" >
       < property name = "song" value = "Jingle Bells" />
       < property name = "age" value = "37" />
    </ bean >
注意 value 属性的使用,字段是 String int 没有什么区别, Spring 根据字段属性来自动决定正确的类型。因此, age int Spring 自动把 37 转换成 int 类型的。
使用 <property> 来对普通的属性值来赋值非常不错,但 DI 应该是比这样写在 xml 文件里更好的东西。 DI 插入的真实数据 是在程序中合作的对象中的,因此它们不需要捆绑在一起。 Kenny 的程序示例一下如何做。
2.3.2使用其他的bean
Kenny 可以使用任何给他的乐器,只要这个乐器继承与 Instrument 接口。当然, kenny 有最喜欢的乐器, saxophone ,下面代码定义一个 saxophone
package com.springinaction.springidol;
 
public class Saxophone implements Instrument {
    public Saxophone() {}
    public void play() {
       System. out .println( "TOOT TOOT TOOT" );
    }
}
在给 kenny 演奏前,必须要把它定义一下
< bean id = "saxophone" class = "com.springinaction.springidol.Saxophone" />
那么 kenny bean 定义也要修改一下
< bean id = "kenny" class = "com.springinaction.springidol.Instrumentalist" >
    < property name = "song" value = "Jingle Bells" />
    < property name = "instrument" ref = "saxophone" />
</ bean >
现在 kenny 已经被注入了所有的属性,并且可以开始演出。跟 duke 一样,我们可以这样来执行:
String path=”com/springinaction/springidol/spring-idol.xml”;
ApplicationContext context = new ClassPathXmlApplicationContext(path);
Performer performer = (Performer)context.getBean(“kenny”);
performer.perform();
这并不是 idol 比赛,但可以是 kenny 实验一下,打印输出:
Playing Jingle Bells : TOOT TOOT TOOT
同时,这个例子还展示了一个重要的地方,如果你跟 duke 执行的代码比较,你发现没什么不一样,但是,唯一的不同点在于,从 Spring 获得的名字不同。代码是相同的,但产生了一个魔术师,一个演奏者。
这不是 spring 的优点,而是对接口编程的号称。通过一个 Performer 接口的对象,我们可以使用任何 performer ,不论是什么诗人还是弹琴的。 Spring 因此鼓励使用 interface 。不过你会看到,面向接口编程和 Spring DI 是代码更松散。
上面提过, kenny 可以演奏各种乐器,现在给他一个钢琴。代码如下:
package com.springinaction.springidol;
 
public class Piano implements Instrument {
    public Piano() {}
 
    public void play() {
       System. out .println( "PLINK PLINK PLINK" );
    }
}
Bean 的声明如下
< bean id = "piano" class = "com.springinaction.springidol.Piano" />
想让 kenny 演奏钢琴, kenny bean 也需要改一下。
    < bean id = "kenny" class = "com.springinaction.springidol.Instrumentalist" >
       < property name = "song" value = "Jingle Bells" />
       < property name = "instrument" ref = "piano" />
    </ bean >
这样, kenny 就可以弹钢琴了,代码不需要任何改变。因为 Instrumentalist 只通过 Instrument 接口知道它本身的 instrument 的属性。这样, kenny 可以弹 saxophone 或者 piano ,两者分散。如果 kenny 想演奏 hammered dulcimer ,只需要加入一个类,并且修改 xml 文件即可。
 
内部类注入
86-87 I don’t care about that. Maybe I will look it later. But not now.
 

2.3.3 捆绑集合

到了现在,介绍了spring配置基本类型(通过value)和其他类(通过ref)但valueref只有在你的属性是单一的时候才有效。那么当属性是复数(就是集合)时spring怎么做呢?

Spring提供了4个类型的集合配置元素。参看2.3

 

<list><set>当属性是array或者是一些java.util.Collection时候非常有用。下面会看到,实际实现的用来定义属性的collection,跟使用<list>还是<set>没有任何关系。两个元素都可以不经修改的使用在任何collection上。

对于<map><props>,对应是java.util.Mapjava.util.Properties。这些都是值键对于的一对一对的。唯一两个不同就是props要求值键都是StringMap则没有要求。

下面是在spring中捆绑collectionHank现在来到了SpringIdel舞台。他是一个人的乐队,跟kenny一样,他能够演奏多种乐器,不过hank是同时演奏。Hank的代码如下:

package com.springinaction.springidol;

 

import java.util.Collection;

 

public class OneManBand implements Performer {

    private Collection<Instrument> instruments;

    public OneManBand() {}

 

    public void perform() throws PerformanceException {

       for(Instrument instrument : instruments){

           instrument.play();

       }

    }

 

    public void setInstruments(Collection<Instrument> instruments) {

       this.instruments = instruments;

    }

}

程序中,当OnManBand执行perform方法的时候对collection进行遍历。这里最重要的是instrutment的注入是通过setter方法。看看Spring怎么支持这个collection

 

ListsArrays

Hank要使用乐器,用list来提供给他

    <bean id="hank" class="com.springinaction.springidol.OneManBand">

       <property name="instruments">

           <list>

              <ref bean="guitar"/>

              <ref bean="cymbal"/>

              <ref bean="harmonica"/>

           </list>

       </property>

    </bean>

<list>元素包含1个或多个值。<ref>用来指向在SpringContext里的其它bean的实例,配置了hank可以弹奏guitarcymbalharmonica。这里可以使用其它Spring的赋值的元素,比如<bean>,<value>甚至<null/>。另外,list可以包含另外一个list,多维概念。

OneManBand类的代码中,instruments使用的是jdk1.5java.util.Collection。但<List>用来工作在那些的属性,它们是实现Collection或者是一个数组。就是说,<list>在以下的代码上照常工作

java.util.List<Instrument> instruments;

Instrument[] insruments;

 

Sets

<list>元素更关心的是Spring如何处理这些collection,而不是它的类型。你可以在用到List的地方改用set<set><list>没有的好处:保证每个元素唯一。不一样的元素会被忽略。

<list>一样,<set>的元素类型也是collectionarray

Maps

OneManBand执行时,每种乐器的声音在perform方法中被打印出来。但我们想看到每个音符是哪个乐器弹奏的,代码需要修改一下:

package com.springinaction.springidol;

 

import java.util.Map;

 

public class OneManBand implements Performer {

    private Map<String,Instrument> instruments;

    public OneManBand() {}

 

    public void perform() throws PerformanceException {

       for(String key : instruments.keySet()){

           System.out.println(key + " : ");

           Instrument instrument = instruments.get(key);

           instrument.play();

       }

    }

 

    public void setInstruments(Map<String,Instrument> instruments) {

       this.instruments = instruments;

    }

}

这个代码中,instruments是由键值对组成的,在xml文件中使用下面的定义:

    <bean id="hank" class="com.springinaction.springidol.OneManBand">

       <property name="instruments">

           <map>

              <entry key="GUITAR" value-ref="guitar"/>

              <entry key="CYMBAL" value-ref="cymbal"/>

              <entry key="HARMONICA" value-ref="harmonica"/>

           </map>

       </property>

    </bean>

<map>元素定义了一个map类型,每一个entry元素定义了map的一个成员。上个例子,key定义了键,value-ref定义了引用的beanid

下图是entry里面的元素的含义。

<map>是唯一一个能把不止是String的类型插入的键值对的方法。下面介绍Props

Props

如果键值都是String,那么就要用到java.util.Properties类了。现在把OneManBand修改一下:

package com.springinaction.springidol;

 

import java.util.Iterator;

import java.util.Properties;

 

public class OneManBand implements Performer {

    private Properties instruments;

    public OneManBand() {}

 

    public void perform() throws PerformanceException {

       for (Iterator iter = instruments.keySet().iterator(); iter.hasNext();) {

           String key = (String)iter.next();

           System.out.println(key + " : " + instruments.getProperty(key));

       }

    }

    public void setInstruments(Properties instruments) {

       this.instruments = instruments;

    }

}

Xml中做如下修改

    <bean id="hank" class="com.springinaction.springidol.OneManBand">

       <property name="instruments">

           <props>

              <prop key="GUITAR">STUM STUM STUM</prop>

              <prop key="CYMBAL">CRASH CRASH CRASH</prop>

              <prop key="HARMONICA">HUM HUM HUM</prop>

           </props>

       </property>

    </bean>

This is easy to understand the code, it’s not necessary to talk about it.

有些可能有些混淆,看一下

l         <property>是向bean注入一个值

l         <props>Properties定义的一个元素

l         <prop><props>的一个元素

2.3.4 捆绑空值

几乎所有情况,都要把值或者java的引用放入一个bean的属性中,但如果要你放入null呢?

对于properties,可以这样

<property name=”someProperty”><null/></properties>

有时需要用null来覆盖自动捆绑,什么是自动捆绑?下面将会讲述。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值