从头认识Spring-1.1 什么是依赖注入?为什么须要依赖注入?

这一章节我们来讨论一下什么是依赖注入?为什么须要依赖注入?

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

时间: 2024-08-25 14:00:21

从头认识Spring-1.1 什么是依赖注入?为什么须要依赖注入?的相关文章

spring 四种依赖注入方式以及注解注入方式

平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化, 而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员, 而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做. spring有多种依赖注

spring学习——Ioc基础四(Di之循环依赖)

一. 什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不是循环调用,循环调用是方法之间的环调用.如图3-5所示: 图3-5 循环引用 循环调用是无法解决的,除非有终结条件,否则就是死循环,最终导致内存溢出错误. Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循

Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理

    注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果. 手工装配依赖对象  手工装配依赖对象,在这种方式中又有两种编程方式 在xml配置文件中,通过在bean节点下配置,上边博客已经讲解,再次不在缀余. 在java代码中使用@Autowired或@Resource注解方式进行装配.但我们需要在xml配置文件中配置以下信息: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <be

spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差

代码: 为了探寻  '@Resource', '@Autowired', 和'@Inject'如何解决依赖注入中的问题,我创建了一个"Party"接口,和它的两个实现类"Person","Organization".这样我就可以在注入Bean的时候不必使用具体类型(指使用接口类型即可).这样做也方便我研究当一个接口有多个实现类与之匹配的时候Spring是如何解决依赖注入的不确定性的. public interface Party {} packa

Spring.NET依赖注入框架学习--简单对象注入

Spring.NET依赖注入框架学习--简单对象注入 在前面的俩篇中讲解了依赖注入的概念以及Spring.NET框架的核心模块介绍,今天就要看看怎么来使用Spring.NET实现一个简单的对象注入 常用文件 我们使用Spring.Net 框架经常要使用到的是以下文件: Common.Logging.dll  包含了Spring.Net日志方面的功能(必须) Spring.Core.dll       包含了Spring.Net 的核心库(必须) Spring.Data.dll       包含了

浅析Spring IOC、依赖注入(DI)和依赖查找(DL)

为什么要用IOC? 第一:对象的实例化不是一件简单的事情,比如对象的关系比较复杂,依赖关系往往需要程序员去维护,这是一件非常头疼的事. 第二:解耦,由容器去维护具体的对象 第三:托管了类的产生过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分过程交给容器,应用程序则无需去关心类是如何完成代理的 控制反转(Inverse of Control) 控制反转即IoC(Incersion of Control),从字面上理解就是控制反转,将对在自身对象中的一个

spring学习2:基于注解+xml实现ioc和依赖注入

spring学习2:基于注解+xml实现ioc和依赖注入 一.在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&qu

Spring——setter方式注入和构造函数方式注入

先写一个比较常见的结构: 其中UserDao跟UserManagerImpl是层与层之间的接口. 下面用这些类来演示setter方式注入跟构造函数注入来解决Manager层注入Dao问题. 一,setter方式注入 首先要在Manager实现类中定义Dao的私有成员变量,并为此变量添加set方法,注入的时候会自动调用这个set方法对成员变量进行赋值. 之后在配置文件中定义依赖关系: <beans xmlns="http://www.springframework.org/schema/be

依赖倒置,控制反转,依赖注入

好的文章,总是担心消失,自己保存一遍,这里是原文 向依赖关系宣战 依赖倒置.控制反转和依赖注入辨析在<道法自然——面向对象实践指南>一书中,我们采用了一个对立统一的辩证关系来说明“模板方法”模式—— “正向依赖 vs. 依赖倒置”(参见:<道法自然>第15章[王咏武, 王咏刚 2004]).这种把“好莱坞”原则和 “依赖倒置”原则等量齐观的看法其实来自于轻量级容器PicoContainer主页上的一段话: “控制反转(Inversion of Control)的一个著名的同义原则是