您的位置:首页 > 编程语言 > Java开发

Spring In Action(二):基于XML配置装配bean

2017-05-29 20:52 741 查看
虽然项目中常用的是通过注解的方式装配bean,但是XML文件配置作为最初的配置方式,对于Spring学习者来说,还是很有必要学习一下的。

首先来看例子:

一、简单的<bean>配置

(1)假如有一个选秀比赛,有很多多才多艺的参赛者,首先,为这些参赛者定义一个Performer表演者接口,接口中有一个表演perform方法

/**
* 表演者接口
*/
public interface Performer {
void perform();//表演方法
}


(2)定义一个歌手类,实现Performer接口,类中包含一个nameOfSong属性,属性值为twinkle twinkle little star 一闪一闪亮晶晶

/**
* 歌手类
*/
public class Singer implements Performer{
//歌名
private String nameOfSong="Twinkle twinkle little star";

public void perform() {
System.out.println("I can sing "+nameOfSong);
}
}


(3)现在有一参赛者duke想要唱这首歌,让我们来为duke实例化一个Singer

         在applicationContext.xml中配置bean,定义一个dukeSinger的id,作为在Spring容器中的引用,class为Singer类的完整路径

         <bean>是Spring容器中最基本的配置单元,通过该元素Spring将创建一个对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
<!--配置bean-->
<bean id="dukeSinger" class="com.study.xmlconfig.Singer"></bean>

</beans>


(4)创建单元测试PerformerTest

package com.study.xmlconfig;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PerformerTest {

@Test
public void performTest(){
//实例化spring上下文,指定要加载的配置文件
ApplicationContext context=new ClassPathXmlApplicationContext("classpath*:/spring/applicationContext.xml");
Performer duke= (Performer) context.getBean("dukeSinger");//根据id从配置文件中获取bean
duke.perform();
}
}


(5)运行结果,可以看到控制台上打印了I can sing Twinkle twinkle little star



二、构造器注入

(1)duke作为参赛者,只会唱一首一闪一闪亮晶晶肯定是不行的,假如评委想让他唱指定的某个歌曲呢?现在来修改一下Singer类,为类添加一个带有歌名的构造函数

/**
* 歌手类
*/
public class Singer implements Performer{
//歌名
private String nameOfSong="";

public Singer(String nameOfSong){
this.nameOfSong=nameOfSong;
}
public void perform() {
System.out.println("I can sing "+nameOfSong);
}
}

(2)修改applicationContext.xml文件,通过构造器为duke指定一个歌名,让duke唱一首《长发公主》插曲I see the light吧

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
<!--配置bean-->
<bean id="dukeSinger" class="com.study.xmlconfig.Singer">
<constructor-arg value="I see the light"></constructor-arg><!--通过构造器传入参数-->
</bean>

</beans>


(3)运行单元测试,此时控制台输出内容变为了I can sing I see the light



(4)歌唱完了,到了自我发挥的时候了,duke其实不仅会唱歌,还会跳HipHop,让duke为我们跳个舞吧!首先定义一个Dance舞蹈的接口

/**
* 舞蹈接口
*/
public interface Dance {
/**
* 跳舞方法
*/
void daning();
}
然后定义HipHop类,实现Dance接口

/**
* Hiphop实现类
*/
public class HipHop implements Dance{
public void daning() {
System.out.println("start hip-hop");
}
}


(5)修改applicationContext.xml文件,为HipHop注册bean
<!--hiphop bean-->
<bean id="hiphop" class="com.study.xmlconfig.HipHop">
</bean>


dukeSinger通过ref属性引用hiphop bean

<!--配置bean-->
<bean id="dukeSinger" class="com.study.xmlconfig.Singer">
<constructor-arg value="I see the light"></constructor-arg><!--通过构造器传入参数-->
<constructor-arg ref="hiphop"></constructor-arg><!--引用hiphop bean,通过构造器注入实例-->
</bean>


完整的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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--组件自动扫描配置-->
<!--<context:component-scan base-package="com.study.autoconfig"></context:component-scan>-->

<!--配置bean--> <bean id="dukeSinger" class="com.study.xmlconfig.Singer"> <constructor-arg value="I see the light"></constructor-arg><!--通过构造器传入参数--> <constructor-arg ref="hiphop"></constructor-arg><!--引用hiphop bean,通过构造器注入实例--> </bean>

<!--hiphop bean-->
<bean id="hiphop" class="com.study.xmlconfig.HipHop">
</bean>
</beans>


(6)单元测试,可以看到duke唱完歌,开始了hiphop



三、Bean属性注入

之前,我们使用了<constructor-arg>的方式为属性进行了注入,现在来看一下<property> byName方式

 (1)首先来修改一下Singer,去掉构造函数,为属性生成get set方法

/**
* 歌手类
*/
public class Singer implements Performer{
//歌名
private String nameOfSong;

//舞蹈
private Dance dance;

public void perform() {
System.out.println("I can sing "+nameOfSong);
dance.daning();//跳舞
}

//生成get set方法
public String getNameOfSong() {
return nameOfSong;
}

public void setNameOfSong(String nameOfSong) {
this.nameOfSong = nameOfSong;
}

public Dance getDance() {
return dance;
}

public void setDance(Dance dance) {
this.dance = dance;
}

}


 (2)修改xml配置文件,使用<property>的byName方式,为属性注入值。name="nameOfSong"表示寻找Singer中nameOfSong属性,然后使用该属性的set方法,将value值注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
<bean id="dukeSinger" class="com.study.xmlconfig.Singer">
<!--通过byName方式注入,寻找Singer中名为nameOfSong属性,并使用set方法,注入value值-->
<property name="nameOfSong" value="twinkle twinkle little star"></property>
<property name="dance" ref="hiphop"></property><!--同理,只不过使用ref引用的方式,使用set方法为dance注入实例-->
</bean>

<!--hiphop bean-->
<bean id="hiphop" class="com.study.xmlconfig.HipHop">
</bean>
</beans>


 (3)单元测试



四、autowired自动装配

autowired共有四种装配方式:

(1)byName方式

         将与bean的属性具有相同名字(或ID)的其他bean自动装配到其属性中。

(2)byType方式

        将与bean的属性具有相同类型的其他bean自动装配到其属性中,如果存在多个类型相同的bean,则抛出异常。

(3)constructor方式

        把与bean的构造器参数具有相同类型的其他bean自动装配到对应的参数中。

(4)autodetect方式

        首先使用constructor进行装配,如果失败,使用byType进行装配。

简单看一下byName和byType的使用:

(1)singer类

/**
* 歌手类
*/
public class Singer implements Performer{
//歌名
private String nameOfSong;

//舞蹈
private Dance dance;

public void perform() {
System.out.println("I can sing "+nameOfSong);
dance.daning();//跳舞
}

//生成get set方法
public String getNameOfSong() {
return nameOfSong;
}

public void setNameOfSong(String nameOfSong) {
this.nameOfSong = nameOfSong;
}

public Dance getDance() {
return dance;
}

public void setDance(Dance dance) {
this.dance = dance;
}

}
(2)byName方式

         修改配置文件,加入autowired=byName的方式,singer类中有一个属性名为dance的对象,将配置文件中为HipHop配置的bean的id改为dance,与singer中的属性名就一致了,此时就可以通过byName的方式,为Singer自动注入dance

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
<!--通过byName方式注入,在spring容器中寻找id为dance的bean,使用set方法为Singer中的dance注入-->
<bean id="dukeSinger" class="com.study.xmlconfig.Singer" autowire="byName">
<property name="nameOfSong" value="twinkle twinkle little star"></property>
</bean>

<!--修改id为dance,与Singer中的dance属性名保持一致-->
<bean id="dance" class="com.study.xmlconfig.HipHop">
</bean>
</beans>


(3)byType方式

         Singer属性中有一个Dance对象,而HipHop类实现了Dance类,因此会将id为hiphop的bean为Singer的dance注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
<!--通过byType方式注入,在spring容器中寻找类型为Dance的bean,使用set方法为Singer中的dance注入-->
<bean id="dukeSinger" class="com.study.xmlconfig.Singer" autowire="byType">
<property name="nameOfSong" value="twinkle twinkle little star"></property>
</bean>

<bean id="hiphop" class="com.study.xmlconfig.HipHop">
</bean>
</beans>

关于依赖注入:

依赖注入:对象的依赖关系由负责协调系统中各个对象的第三方组件在创建对象时设定,对象无需自行创建或者管理它们的依赖关系,依赖关系将被自动注入到需要它们的对象中去。(Spring in Action)

举例说明:

以上面代码第一个为例

/**
* 歌手类
*/
public class Singer implements Performer{
//歌名
private String nameOfSong="Twinkle twinkle little star";

public void perform() {
System.out.println("I can sing "+nameOfSong);
}
}


在这里,nameOfSong属性已经被写死,假如我们想改为其他的歌曲,就要修改Singer类,如果nameOfSong是一个对象的话,就造成了对象之间的高耦合,为了避免过高的耦合,我们改为了在spring容器中通过构造器注入的方式,为Singer传入参数,Singer的实例化也是由Spring容器完成,根据我的理解,把对象交给spring管理,由spring创建实例并管理对象之间的依赖,就是spring中的依赖注入。

源码下载:http://download.csdn.net/detail/lom9357bye/9856022

参考:Spring in Action 第三版
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  IDEA spring xml bean