bean依赖注入

  • 1.通过构造方法注入
  • 2.通过属性设值方法注入
  • a.属性值及引用bean注入
  • b.bean级联属性注入
  • c.单独属性文件值注入
  • d.集合类型值注入
  • e.升级配置p命名空间


1.通过构造方法注入

构造方法指的是一个类中对类进行初始化的方法,构造方法有两种:一种是无参构造方法;一种是有参构造方法。类如果没有定义构造方法,都会具有一个隐式的无参构造方法来保证创建对象时初始化。
首先创建一个Person类,并定义一个有参构造方法,如下:

package com.me.spring;
public class Person {
    private String name; //姓名
    private int age; // 年龄
    private double weight; // 体重
    public Person(String name, int age,double weight){
        this.name = name;
        this.age = age;
        this.weight = weight;
    }
    // getter and setter......
}

bean配置,构造方法属性注入使用constructor-arg:

<bean id="person" class="com.me.spring.Person">
    <constructor-arg value="Kim"></constructor-arg>
    <constructor-arg value="20"></constructor-arg>
    <constructor-arg value="78.6"></constructor-arg>
</bean>

测试运行:

我是Kim,今年20岁,体重78.6公斤!

当然,bean配置中参数的顺序位置是可以不固定的,此时可以通过指定参数的位置标号实现准确注入,如:

<bean id="person" class="com.me.spring.Person">
    <constructor-arg value="20" index="1"></constructor-arg>
    <constructor-arg value="Kim" index="0"></constructor-arg>
    <constructor-arg value="78.6" index="2"></constructor-arg>
</bean>

2.通过属性设值方法注入

a.属性值及引用bean注入

通过属性注入有两种注入类型,一种是一般属性,一种是引用类型的属性,引用类型属性就是一个对象中有引用其他对象作为自己的一个属性,如下:
Person类除了一般属性:姓名和年龄,还有一个引用类型属性Lenovo对象

package com.me.spring;
public class Person {
    private String name; //姓名
    private int age; // 年龄
    private Lenovo lenovo; // 联想电脑
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Lenovo getLenovo() {
        return lenovo;
    }
    public void setLenovo(Lenovo lenovo) {
        this.lenovo = lenovo;
    }
}

bean的配置:

<bean id="person" class="com.me.spring.Person">
    <property name="name" value="Tom"></property>
    <property name="age" value="20"></property>
    <property name="lenovo" ref="lenovo"></property>
</bean>
<bean id="computer" class="com.me.spring.Computer">
    <property name="type" value="电脑"></property>
    <property name="color" value="黑色"></property>
</bean>
<bean id="lenovo" class="com.me.spring.Lenovo">
    <property name="type" value="笔记本电脑"></property>
    <property name="vendor" value="Lenovo"></property>
    <property name="size" value="15"></property>
</bean>

以上的配置,设值依赖注入用的都是属性property,但是需要注意的不同点就是,当注入的属性是一般属性时,使用的是value;当注入的属性是引用数据类型是需要使用ref表示引用。

运行测试:

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Person person = (Person)context.getBean("person");
System.out.println("我是"+person.getName()+",有一台电脑:"+person.getLenovo().toString());

运行结果:

我是Tom,有一台电脑:类型[笔记本电脑],颜色[黑色],厂商[Lenovo],尺寸[15]

b.bean级联属性注入

若bean有引入对象注入的话,Spring还提供有级联属性值注入方式,如:

<bean id="person" class="com.me.spring.Person">
    <property name="name" value="Tom"></property>
    <property name="age" value="20"></property>
    <property name="lenovo" ref="lenovo"></property>
    <property name="lenovo.color" value="白色"></property>
</bean>

此时,测试运行结果:

我是Tom,有一台电脑:类型[笔记本电脑],颜色[白色],厂商[Lenovo],尺寸[15]

级联注入允许在注入的bean中修改被注入bean的属性值,以上把电脑的颜色属性由黑色修改为白色。
如果我想用<>把电脑的类型强调一下,该如何处理呢?直接加上,由于<>是特殊符号,而且会与大于小于符号无法区分,所以要用<![CDATA[]]>特殊处理一下,如下,使用value节点:

<bean id="lenovo" class="com.me.spring.Lenovo" parent="computer">
    <property name="type">
        <value><![CDATA[<笔记本>电脑]]></value>
    </property>
    <property name="vendor" value="Lenovo"></property>
    <property name="size" value="15"></property>
</bean>

运行结果:

我是Tom,有一台电脑:类型[<笔记本>电脑],颜色[白色],厂商[Lenovo],尺寸[15]

c.单独属性文件值注入

这种注入在配置数据库连接是最常见的配置数据库连接的四个属性,这种方式注入属性值,需要首先新建一个key-value文件,如新建一个spring.properties,内容如下:

name=Kim
age=23

检查bean的配置文件中是否已经加入context命名空间:

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

此时,还需要加入加载属性文件的配置:

<context:property-placeholder location="spring.properties"/>
<bean id="person" class="com.me.spring.Person">
    <property name="name" value="${name}"></property>
    <property name="age" value="${age}"></property>
</bean>

运行测试,结果:

我是Kim,今年23!

注:一定要加入context命名空间

d.集合类型值注入

集合当然也是能够注入的,比如:Person类中新增一个鞋子属性,一个人可有很多双的鞋子,用集合记录:

package com.me.spring;

import java.util.List;

public class Person {
    private String name; //姓名
    private int age; // 年龄
    private List<String> shoes; // 鞋子集合
    // getter and setter......
}

配置bean的鞋子集合,如下:

<bean id="person" class="com.me.spring.Person">
    <property name="name" value="${name}"></property>
    <property name="age" value="${age}"></property>
    <property name="shoes">
        <list>
            <value>黑鞋子</value>
            <value>白鞋子</value>
            <value>红鞋子</value>
        </list>
    </property>
</bean>

测试运行结果:

我是Kim,今年23!我的鞋子有:[黑鞋子, 白鞋子, 红鞋子]

如果注入的集合元素是引用对象的情况狂,则bean配置市容ref而非value,如下:

<bean id="person" class="com.me.spring.Person">
    <property name="name" value="${name}"></property>
    <property name="age" value="${age}"></property>
    <property name="shoes">
        <list>
            <ref bean="shoes1"/>
            <ref bean="shoes2"/>
            <ref bean="shoes3"/>
        </list>
    </property>
</bean>

其他类型的集合都与之类似,不再举例。有点不同的是key-value类型的Map集合,如果是Map集合,使用props属性,bean的配置如下:

<bean id="person" class="com.me.spring.Person">
    <property name="name" value="${name}"></property>
    <property name="age" value="${age}"></property>
    <property name="shoes">
        <props>
            <prop key="black">皮鞋</prop>
            <prop key="red">运动鞋</prop>
        </props>
    </property>
</bean>

e.升级配置p命名空间

从上面的bean配置已经不难发现,如果bean特别多的话,配置文件会比较的庞大,为了进一步简化bean的配置文件,从2.5版本开始Spring新增了一种新的命名空间,就是p,具体使用如下:
对了,既然是新的命名空间,那肯定要在文件头上加上去:

xmlns:p="http://www.springframework.org/schema/p"

之前是这样的:

<bean id="person" class="com.me.spring.Person">
    <property name="name" value="${name}"></property>
    <property name="age" value="${age}"></property>
    <property name="lenovo" ref="lenovo"></property>
</bean>

使用p命名空间是:

<bean id="person" class="com.me.spring.Person" p:name="Tomp" p:age="22" p:lenovo-ref="lenovo"></bean>

这么一来bean使用p命名空间,确实简化了不少配置。但是,对于一个项目中成千上万不计其数的bean来说,真正使用起来配置文件的体量依然很庞大。不着急,循序渐进,下回我们要请出真正的杀手锏,争取消灭这么繁杂的bean配置!