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可以使用<property>元素配置Bean的属性——通过属性的setter方法注入。(注意此处的property而不是attribute,所以,这里寻找的实际上是属性对应的setter方法,而不是成员变量

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

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

<property>元素没有限制注入值的类型,其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配置声明:
<?xml version="1.0" encoding="UTF-8"?>

<!-- 引用Spring的多个Schema空间的格式定义文件 -->

<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 elementuseful for…
<list>wiring list of values, allowing duplicates
<set>wiring set of values, ensuring no duplicates
<map>wiring a collection of name-value pairs where name and value can be of any type
<props>wiring a collection of name-value pairs where name and value are both strings

- 当属性为任意的java.util.Collection类型时,<list>和<set>在使用时可以互换。

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

示例:现在来了一位全能型的音乐演奏者,能演奏多种乐器,也实现了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<Instrument>  instruments;

    @Override
    public void perform() throws PerformanceException {
        for(Instrument instrument : instruments)
            instrument.play();
    }

    public Collection<Instrument> getInstruments() {
        return instruments;
    }

    public void setInstruments(Collection<Instrument> 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<String, Instrument>  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<String, Instrument> getInstruments() {
        return instruments;
    }

    public void setInstruments(Map<String, Instrument> 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值,或者覆盖自动装配的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值