Spring的依赖注入

来源:互联网 发布:如果世上不再有猫 知乎 编辑:程序博客网 时间:2024/06/05 11:36

这篇文章主要是讲述:什么是Spring中的依赖注入,以及为什么要使用依赖注入。

1. 什么是依赖注入(DI-Dependency Injection)

依赖注入也叫控制反转(Inversion of Control,英文缩写为IOC),以我个人的理解简单点说就是:创建对象不再通过new关键字,而是从spring容器中去取,对象的创建是使用注入这种形式。

2. 为什么要使用依赖注入?

使用依赖注入主要是为了两点:
1. 解耦
2. 方便进行测试

3. 测试用例:

我们以歌唱家唱歌这个实际的情况为例子分别就使用依赖注入和不使用依赖注入做分析:

不使用依赖注入的情况

首先得有个歌曲类 Song

package spring.ch1.topic1;/** * Created by louyuting on 17/1/20. */public class Song {    @Override    public String toString() {        return "sing a song ";    }}

再创建演唱者:Singer

package spring.ch1.topic1;/** * Created by louyuting on 17/1/20. * 以歌唱家唱歌这个为例,在没有依赖注入的情况下的实现; * 主要问题:紧密耦合,要测试Singer必须要new一个song对象出来. *         Singer只能唱指定的song,如果换歌必须修改代码. */public class Singer {    private Song song;    public Singer() {        this.song = new Song();//强耦合的地方    }    public void singSong(){        System.out.println(song.toString());    }    public static void main(String[] args) {        new Singer().singSong();    }}

运行结果:

/*** //output:~sing a song*/

上面的代码明显的耦合紧密,会出现两个问题:
(1)需要测试Singer的时候,必须new一个song实例对象出来
(2)Singer只能是唱指定的song,如果换一首,就必须重新修改代码。
而我们想要的是低耦合,尽量不修改代码。

上面完整代码的github地址

使用依赖注入的代码实例

歌曲类Song,我通过构造器增加了歌曲的名字,这样可以通过依赖注入变化不同的曲目,使得歌曲类更加灵活。

package spring.ch1.topic2;/** * Created by louyuting on 17/1/20. * */public class Song {    private String name;    public Song(String name) {        this.name = name;    }    @Override    public String toString() {        return "sing a song "+ this.name;    }}

歌唱家的类Singer 不变:

package spring.ch1.topic2;/** * Created by louyuting on 17/1/20. */public class Singer {    private Song song=null;    public Singer(Song song) {        this.song = song;    }    public void singSong(){        System.out.println(song.toString());    }}

为了测试方便,我们增加了一个测试类。

package spring.ch1.topic2;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/** * Created by louyuting on 17/1/20. * 这里使用依赖注入的方式测试:依赖注入采用反射机制实例化的. * */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:ApplicationContext-test.xml"})public class SingerTest {    @Autowired    private ApplicationContext applicationContext;    @Test    public void testSinger(){        Singer jack = (Singer)applicationContext.getBean("jack");        jack.singSong();        Singer rose = (Singer)applicationContext.getBean("rose");        rose.singSong();    }}

接着就是Spring的配置文件:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"       xmlns:aop="http://www.springframework.org/schema/aop"       xsi:schemaLocation="        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">    <bean id="song1"          class="spring.ch1.topic2.Song">        <constructor-arg value="my heart will go on" />    </bean>    <bean id="song2"          class="spring.ch1.topic2.Song">        <constructor-arg value="there will be" />    </bean>    <bean id="jack"          class="spring.ch1.topic2.Singer">        <constructor-arg ref="song1" />    </bean>    <bean id="rose"          class="spring.ch1.topic2.Singer">        <constructor-arg ref="song2" />    </bean></beans>

在配置文件中配置了两首Song的bean和一个Singer的bean。对于构造器的参数,通过 来注入。上面体现了以下两点灵活性:
(1)通过配置不同的歌曲,从而实现歌唱家能够唱不同的歌曲,不像之前的代码那样,只能够唱同一首歌
(2)通过配置,可以重复利用相同的类,来灵活配置不同的歌唱家唱不同的歌曲。

运行结果:

/***//output:~sing a song my heart will go onsing a song there will be*/

上面完整代码的github地址

4. 总结:

1)依赖注入的优点:
(1)对象的定义放在xml里面,我们可以灵活的配置
(2)易于测试
(3)易于装卸

2)依赖注入的缺点:
(1)创建对象的流程麻烦了
(2)由于spring大部分采用反射机制来实现,因此性能一定是个问题

0 0
原创粉丝点击