这一章节我们来讨论一下什么是依赖注入?为什么须要依赖注入?
1.什么是依赖注入?
笔者理解的是:对象的生成不再是通过显示的new,并且到spring容器里面取。对象的创建是使用注入这样的形式
2.为什么须要依赖注入?
(1)解耦
(2)易于測试
我们以歌唱家唱歌这个为样例,在没有使用依赖注入情况下的代码:
package com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1; public class Song { @Override public String toString() { return "a song"; } }
package com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1; public class Singer { private Song song = null; public Singer() { song = new Song();//强耦合的地方 } public void singTheSong() { System.out.println(song.toString()); } public static void main(String[] args) { new Singer().singTheSong(); } }
输出:
a song
上面的代码耦合紧密。会出现两个问题:
(1)须要測试Singer的时候,必须new一个song出来
(2)Singer仅仅能是唱指定的song,假设换一首。就必须又一次改动代码。
我们换成依赖注入形式:
(注意,因为代码比較多,并且我是使用maven形式构建项目,因此。详细的代码能够到我的github去查看,本文最底部有我的github地址)
package com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1; public class Song { private String name; public Song(String name) { this.name = name; } @Override public String toString() { return "the song:" + name; } }
歌曲类我们添加了歌曲的名字,这样能够通过依赖注入变化不同的曲目,使得歌曲类更加灵活
package com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1; public class Singer { private Song song = null; public Singer(Song song) { this.song = song; } public void singTheSong() { System.out.println(song.toString()); } }
歌唱家的类不变。
package com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1; 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; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:ApplicationContext-test.xml" }) public class SingerTest { @Autowired private ApplicationContext applicationContext; @Test public void testSinger() { Singer singer = applicationContext.getBean(Singer.class); singer.singTheSong(); } }
为了測试方便,我们添加了一个測试类。
<? 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="com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1.Song"> <constructor-arg value="my heart will go on" /> </bean> <bean id="singer" class="com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1.Singer"> <constructor-arg ref="song1" /> </bean> <bean id="song2" class="com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1.Song"> <constructor-arg value="there will be" /> </bean> </beans>
我们重点来说一下上面的配置文件。因为灵活性的实现就体如今上面了
(1)通过配置不同的歌曲,从而实现歌唱家能够唱不同的歌曲,不像之前的代码那样。仅仅能够唱同一首歌
(2)通过配置。能够反复利用同样的类,来灵活配置不同的歌唱家唱不同的歌曲(如以下的配置)。
<?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="jack" class="com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1.Singer"> <constructor-arg ref="song1" /> </bean> <bean id="song1" class="com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1.Song"> <constructor-arg value="my heart will go on" /> </bean> <bean id="rose" class="com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1.Singer"> <constructor-arg ref="song2" /> </bean> <bean id="song2" class="com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1.Song"> <constructor-arg value="there will be" /> </bean> </beans>
然后我们仅仅要略微改动一下測试类,而前面的歌唱家和歌曲类不需改动
package com.raylee.my_new_spring.my_new_spring.ch01.topic_1_1; 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; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:ApplicationContext-test.xml" }) public class SingerTest { @Autowired private ApplicationContext applicationContext; @Test public void testJackSinger() { Singer singer = (Singer) applicationContext.getBean("jack"); singer.singTheSong(); } @Test public void testRoseSinger() { Singer singer = (Singer) applicationContext.getBean("rose"); singer.singTheSong(); } }
我们就可以配置出不同的歌唱家唱不同的歌曲。
输出:
the song:my heart will go on
或者
the song:there will be
3.依赖注入的优缺点:
长处:
(1)对象的定义放在xml里面。我们能够灵活的配置
(2)易于測试
(3)易于装卸
缺点:
(1)创建对象的流程麻烦了
(2)因为spring大部分採用反射机制来实现。因此性能一定是个问题
(3)因为对象的定义放在xml。对于使用eclipse来重构就会比較麻烦
总结:这一章节我们主要介绍了什么是依赖注入?为什么须要依赖注入?
我的github:https://github.com/raylee2015/my_new_spring