Spring实例解析之XML装配Bean
@(Spring)
*本文主要参考Spring in action(第三版),并以自己的实例进行了实现。
在Spring中容器负责把需要相互协作的对象引用赋予各个对象。创建应用对象之间协作关系的行为通常称为装配(wiring)
1.maven依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
2.声明Bean
本文将围绕People接口,来渐渐展开。
public interface People {
void doWorking();
}
2.1 声明简单Bean
Himma(搬砖工)实现People接口。并有两个参数,birckNum(砖头数),pitNum(填坑数)。
package com.spring;
public class Himma implements People {
//默认一天搬100块砖
private Integer brickNum = 100;
//默认填5个坑
private Integer pitNum = 5;
public Himma(){
}
public Himma(int brickNum){
this.brickNum = brickNum;
}
public Himma(int brickNum, int pitNum){
this.brickNum = brickNum;
this.pitNum= pitNum;
}
public void doWorking() {
System.out.println("今天搬了"+brickNum+"块砖,还填了"+pitNum+"个坑");
}
public void setBrickNum(Integer brickNum) {
this.brickNum = brickNum;
}
public void setPitNum(Integer pitNum) {
this.pitNum = pitNum;
}
}
2.2 创建Spring的XML配置
传统的XML文件配置方式。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- xiaoMing,实现最基本bean配置 -->
<bean id="xiaoMing" class="com.spring.Himma"></bean>
</beans>
2.3 初步实现
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Himma.xml");
People xiaoming = (People)applicationContext.getBean("xiaoMing");
xiaoming.doWorking();
运行结果:今天搬了100块砖,还填了5个坑
运行结果正常,由Spring实例化的bean正确执行了doWorking方法。
2.4 通过构造器注入
在Spring-Himma.xml中配置,分别实现了构造器注入的几种方式。
<!-- xiaoHong,通过构造器注入 -->
<bean id="xiaoHong" class="com.spring.Himma">
<constructor-arg value="300"></constructor-arg>
</bean>
<!-- xiaoHong,通过构造器注入,指定参数类型。-->
<!-- 如果构造函数都只有一个参数,一个类型为String,一个类型为int,那么Spring将会调用参数类型为String的构造函数 -->
<!--
<bean id="xiaoHong" class="com.spring.Himma">
<constructor-arg type="int" value="300"></constructor-arg>
</bean>
-->
<!-- xiaoGang,通过构造器注入多参数,默认按构造器参数顺序,也可以指定顺序 -->
<bean id="xiaoGang" class="com.spring.Himma">
<constructor-arg value="300"></constructor-arg>
<constructor-arg value="20"></constructor-arg>
</bean>
<!-- xiaoGang,指定参数顺序的构造器注入-->
<!--
<bean id="xiaoGang" class="com.spring.Himma">
<constructor-arg value="300" index="0"></constructor-arg>
<constructor-arg value="20" index="1"></constructor-arg>
</bean>
-->
2.5 Bean的作用域
作用域 | 定义 |
---|---|
singleton | 在每一个Spring容器中,一个bean定义只有一个对象实例(默认) |
prototype | 每次调用都创建一个实例 |
request | 在一次http请求中,每个bean定义对应一个实例。仅在基于web的Spring上下文中有效 |
session | 在一次http session请求中,每个bean定义对应一个实例。仅在基于web的Spring上下文中有效 |
global-session | 在一个全局http session中,每个bean定义对应一个实例。仅在Portlet上下文中有效 |
增添新的类SingHimma。里面增加了一个Song的引用,在其搬砖的时候还能唱首歌。
package com.spring;
public class SingHimma extends Himma{
private Song song;
public SingHimma(){
}
public SingHimma(Song song){
this.song = song;
}
public SingHimma(int brickNum,Song song){
super(brickNum);
this.song = song;
}
@Override
public void doWorking() {
// TODO Auto-generated method stub
super.doWorking();
System.out.println("开始唱歌。。");
song.sing();
}
public void setSong(Song song) {
this.song = song;
}
public void startWork(){
System.out.println("开始上班了");
}
public void endWork(){
System.out.println("下班了");
}
}
package com.spring;
public interface Song {
void sing();
}
FadedSong,SugerSong实现了Song 接口
package com.spring;
public class FadedSong implements Song{
public void sing() {
// TODO Auto-generated method stub
System.out.println("You were the shadow to my light....Did you feel us....");
}
}
package com.spring;
public class SugerSong implements Song{
public void sing() {
// TODO Auto-generated method stub
System.out.println("I'm hurtin baby, I'm broken down...I need your lovin, lovin I need it now...");
}
}
<!-- 通过构造器注入对象引用 -->
<bean id="xiaoXia" class="com.spring.SingHimma">
<constructor-arg value="500"></constructor-arg>
<constructor-arg ref="fadedSong"></constructor-arg>
</bean>
<!-- 通过构造器注入对象引用,使用prototype作用域 -->
<bean id="xiaoZhi" class="com.spring.SingHimma" scope="prototype">
<constructor-arg value="500"></constructor-arg>
<constructor-arg ref="fadedSong"></constructor-arg>
</bean>
<bean id="fadedSong" class="com.spring.FadedSong"></bean>
使用junit来演示scope为默认的singleton与prototype的情况
@Before
public void setUp() throws Exception {
applicationContext = new ClassPathXmlApplicationContext(
"Spring-SingHimma.xml");
}
@Test
public void testxiaoZhi() {
// xiaoXia默认作用域为singleton
SingHimma xiaoXia = (SingHimma) applicationContext.getBean("xiaoXia");
xiaoXia.doWorking();
// 给xiaoXia一首新歌
xiaoXia.setSong(new SugerSong());
// 重新从Spring容器中取得xiaoXia,发现song变成了SugerSong
SingHimma xiaoXia2 = (SingHimma) applicationContext.getBean("xiaoXia");
xiaoXia2.doWorking();
// xiaoZhi作用域为prototype
SingHimma xiaoZhi = (SingHimma) applicationContext.getBean("xiaoZhi");
xiaoZhi.doWorking();
// 给xiaoZhi一首新歌
xiaoZhi.setSong(new SugerSong());
// 重新从Spring容器中取得xiaoZhi,发现song没有变化
SingHimma xiaoZhi2 = (SingHimma) applicationContext.getBean("xiaoZhi");
xiaoZhi2.doWorking();
}
发现xiaoXia通过重新赋值后,第二次调用时song换成了SugerSong。而使用prototype的xiaoZhi则没有改变,两次调用都是同样在xml中配置的FadedSong
运行结果为:
今天搬了500块砖,还填了5个坑
开始唱歌。。
You were the shadow to my light….Did you feel us….
今天搬了500块砖,还填了5个坑
开始唱歌。。
I’m hurtin baby, I’m broken down…I need your lovin, lovin I need it now…今天搬了500块砖,还填了5个坑
开始唱歌。。
You were the shadow to my light….Did you feel us….
今天搬了500块砖,还填了5个坑
开始唱歌。。
You were the shadow to my light….Did you feel us….
2.6 初始化和销毁Bean
观察SingHimma中可以发现两个方法startWork和endWork。可以在XML中将其配置为初始化方法和销毁方法。
<!-- 添加指定的初始化方法和销毁方法 -->
<bean id="xiaoXia" class="com.spring.SingHimma" init-method="startWork" destroy-method="endWork">
<constructor-arg value="500"></constructor-arg>
<constructor-arg ref="fadedSong"></constructor-arg>
</bean>
调用执行
@Before
public void setUp() throws Exception {
applicationContext = new ClassPathXmlApplicationContext(
"Spring-SingHimma.xml");
}
@Test
public void testxiaoXia() {
People xiaoXia = (People) applicationContext.getBean("xiaoXia");
xiaoXia.doWorking();
}
@After
public void destroy() {
// 关闭容器,演示destory-method
((ClassPathXmlApplicationContext) applicationContext).close();
}
执行结果:
开始上班了
今天搬了500块砖,还填了5个坑
开始唱歌。。
You were the shadow to my light….Did you feel us….
下班了
2.7 注入Bean属性
XML配置,使用setter注入属性。
<!-- 注入bean属性 -->
<bean id="xiaoMei" class="com.spring.SingHimma">
<!-- 注入简单值 -->
<property name="brickNum" value="1000"></property>
<property name="pitNum" value="50"></property>
<!-- 装配空值 -->
<!--
<property name="pitNum"><null/></property>
-->
<!-- 引入其他Bean -->
<property name="song" ref="fadedSong"></property>
<!-- 引入内部Bean -->
<!--
<property name="song">
<bean class="com.spring.FadedSong"></bean>
</property>
-->
</bean>
2.8 装配集合
集合元素 | 用途 |
---|---|
<list> | 装配list类型的值,允许重复 |
<set> | 装配set类型的值,不允许重复 |
<map> | 装配map类型的值,名称和值可以是任意类型 |
<props> | 装配properties类型的值,名称和值必须都是String类型 |
为了实现装配集合的实例,增加一个新的类HimmaTeam,搬砖队。通过三种不同的集合注入来展示。
package com.spring;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
public class HimmaTeam implements People{
private Collection<People> peoples;
private Map<String, String> fruits;
private Properties foods;
public HimmaTeam(){
}
public void doWorking() {
// TODO Auto-generated method stub
for (People people : peoples) {
people.doWorking();
}
for (String key : fruits.keySet()) {
System.out.println(key+": 吃了"+ fruits.get(key));
}
for (Object key : foods.keySet()) {
String keyStr = key.toString();
String valueStr = foods.getProperty(keyStr);
System.out.println(keyStr + ": 吃了"+valueStr);
}
}
public void setPeoples(Collection<People> peoples) {
this.peoples = peoples;
}
public void setFruits(Map<String, String> fruits) {
this.fruits = fruits;
}
public void setFoods(Properties foods) {
this.foods = foods;
}
}
XML配置
<!-- 引入Himma与SingHimma的上下文配置 -->
<import resource="Spring-Himma.xml"/>
<import resource="Spring-SingHimma.xml"/>
<bean name="blueTeam" class="com.spring.HimmaTeam">
<property name="peoples">
<!-- 装配list集合 -->
<list>
<ref bean="xiaoMing"/>
<ref bean="xiaoHong"/>
<ref bean="xiaoMei"/>
</list>
</property>
<!-- 装配map集合 -->
<property name="fruits">
<map>
<entry key="apple" value="苹果"></entry>
<entry key="banana" value="香蕉"></entry>
<entry key="pears" value="梨子"></entry>
</map>
</property>
<!-- 装配properties集合 -->
<property name="foods">
<props>
<prop key="rice">米饭</prop>
<prop key="noodles">面条</prop>
<prop key="bread">面包</prop>
</props>
</property>
</bean>
结果:
开始上班了
今天搬了100块砖,还填了5个坑
今天搬了300块砖,还填了5个坑
今天搬了1000块砖,还填了50个坑
开始唱歌。。
You were the shadow to my light….Did you feel us….
apple: 吃了苹果
banana: 吃了香蕉
pears: 吃了梨子
bread: 吃了面包
noodles: 吃了面条
rice: 吃了米饭
下班了
3.小结
以上为Spring的XML装配Bean的一个简单例子。附上github的地址:https://github.com/JunliXia/Spring_WiringBean
4.参考
Spring in action
http://jingyan.baidu.com/article/11c17a2c749a61f446e39d94.html