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配置!