3. 注入Bean的属性

注入Bean的属性

注入简单值

一般来说,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的属性——通过属性的setter方法注入。(注意此处的property而不是attribute,所以,这里寻找的实际上是属性对应的setter方法,而不是成员变量

<bean id="instrumentalist" class="com.li.spring.chineseidol.Instrumentalist">
        <property name="song" value="memory">property>
bean>

一旦Instrumentalist被实例化,Spring就会调用元素所指定属性的setter方法为该属性注入值。

元素没有限制注入值的类型,其value属性可以指定数值类型(int, float, double等)以及boolean、String类型。

引用其他Bean

因为上面的类中还有一个成员变量,是一个乐器接口,因此我们还需要注入乐器接口的实现类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装配属性

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类型时,在使用时可以互换。

  • 分别对应java.util.map和java.util.Properties,要求键值都为String类型,而允许键值为任意类型。

示例:现在来了一位全能型的音乐演奏者,能演奏多种乐器,也实现了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值,或者覆盖自动装配的值。

你可能感兴趣的:(Spring)