Spring之依赖注入的实现方式

版权声明: https://blog.csdn.net/qq_24313635/article/details/81877671

一.IoC的基础知识以及原理:

IoC理论的背景:

在采用面向对象方法设计的软件系统中,底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。即软件系统中对象之间的耦合,对象A和对象B之间有关联,对象B又和对象C有依赖关系,这样对象和对象之间有着复杂的依赖关系,所以才有了控制反转这个理论。

什么是控制反转(IoC):

(1).IoC是Inversion of Control的缩写,有的翻译成“控制反转”,还有翻译成为“控制反向”或者“控制倒置”。

(2).1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IoC 这个概念。简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。IoC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦,如下图所示:

即把各个对象类封装之后,通过IoC容器来关联这些对象类。这样对象与对象之间就通过IoC容器进行联系,但对象与对象之间并没有什么直接联系。

如果去掉IoC容器后系统中的对象A与对象B就有了直接关系,如下图所示:

比如好多的对象类要关联起来的话,就会变得很复杂,如下图所示:

所以提出IoC控制反转是很有必要的。

(3).为什么要把这种方式叫做控制反转呢?

软件系统在没有引入IoC容器之前,对象A依赖对象B,那么A对象在实例化或者运行到某一点的时候,自己必须主动创建对象B或者使用已经创建好的对象B,其中不管是创建还是使用已创建的对象B,控制权都在我们自己手上。

如果软件系统引入了Ioc容器之后,对象A和对象B之间失去了直接联系,所以,当对象A实例化和运行时,如果需要对象B的话,IoC容器会主动创建一个对象B注入到对象A所需要的地方

通过前面的对比,可以看到对象A获得依赖对象B的过程,由主动行为变成了被动行为,即把创建对象交给了IoC容器处理,控制权颠倒过来了,这就是控制反转的由来

IoC的别名:依赖注入(DI)

(1).2004年,Martin Fowler探讨了同一个问题,既然IoC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理对象变为由IoC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection,DI)”。他的这个答案,实际上给出了实现IoC的方法:注入

(2).所谓依赖注入,就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。

(3).所以,依赖注入(DI)和控制反转(IoC)是从不同的角度描述的同一件事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦

使用IoC的好处:

(1).可维护性比较好,非常便于进行单元测试,便于调试程序和诊断故障。代码中的每一个Class都可以单独测试,彼此之间互不影响,只要保证自身的功能无误即可,这就是组件之间低耦合或者无耦合带来的好处。

(2).每个开发团队的成员都只需要关注自己要实现的业务逻辑,完全不用去关心其他人的工作进展,因为你的任务跟别人没有任何关系,你的任务可以单独测试,你的任务也不用依赖于别人的组件,再也不用扯不清责任了。所以,在一个大中型项目中,团队成员分工明确、责任明晰,很容易将一个大的任务划分为细小的任务,开发效率和产品质量必将得到大幅度的提高。

(3).可复用性好,我们可以把具有普遍性的常用组件独立出来,反复应用到项目中的其它部分,或者是其它项目,当然这也是面向对象的基本特征。显然,IoC更好地贯彻了这个原则,提高了模块的可复用性。符合接口标准的实现,都可以插接到支持此标准的模块中。

(4).IoC生成对象的方式转为外置方式,也就是把对象生成放在配置文件里进行定义,这样,当我们更换一个实现子类将会变得很简单,只要修改配置文件就可以了,完全具有热插拨的特性。

IoC的原理:

控制反转是Spring框架的核心。其原理是基于面向对象(OO)设计原则的The Hollywood Principle:Don't call us, we'll call you(别找我,我会来找你的)。也就是说,所有的组件都是被动的,所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容器负责管理。简单的来讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控,即在一个类中调用另外一个类。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,即所谓反转

主要的装配机制:

Spring提供了三种主要的装配机制

  • 基于注解;
  • 基于java代码;
  • 基于xml;

注解装配

①CDPlayerConfig代码:

@ComponentScan
public class CDPlayerConfig{
 
}

②CD代码:

@Component
public class CD {
	public void play() {
		System.out.println("...童年的纸飞机飞回我手里...");
	}
}

③CDPlayer代码:

@Component
public class CDPlayer {

	@Autowired
	private CD cd;

	public void play() {
		cd.play();
	}
}

Java代码装配

①JavaConfig代码:

@Configuration
public class JavaConfig{
    @Bean 
    public CD cd() {
        return new CD();
    }
}

②CD代码:

public class CD {
	public void play() {
		System.out.println("...童年的纸飞机飞回我手里...");
	}
}

Xml装配

①CD代码:

public class CD {
	public void play() {
		System.out.println("...童年的纸飞机飞回我手里...");
	}
}

②CDPlayer代码:

public class CDPlayer {

	private CD cd;
	/*
        set方法注入,或者是构造方法注入
        */
	public void setCd(CD cd) {
		this.cd = cd;
	}

	public void play() {
		cd.play();
	}
}

③xmlConfig.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:p="http://www.springframework.org/schema/p"
    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="cdPlayer" class="com.yj.spring.xml.CDPlayer">
		<property name="cd" ref="cd"/>
	</bean>
	
	<bean id="cd" class="com.yj.spring.xml.CD"/>
</beans>

测试类

BeanTest代码:

public class BeanTest {
	/**
	 * 基于注解装配
	 */
	@Test
	public void annoTest() {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(CDPlayerConfig.class);
		com.yj.spring.anno.CDPlayer player = ctx.getBean(com.yj.spring.anno.CDPlayer.class);
		player.play();
	}

	
	/**
	 * java代码装配
	 */
	@Test
	public void javaTest() {
		ApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
		com.yj.spring.java.CD player = ctx.getBean(com.yj.spring.java.CD.class);
		player.play();
	}
	
	
	/**
	 * xml装配
	 */
	@Test
	public void xmlTest() {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("xmlConfig.xml");
		com.yj.spring.xml.CDPlayer player = ctx.getBean(com.yj.spring.xml.CDPlayer.class);
		player.play();
	}
}

显示结果:

...童年的纸飞机飞回我手里...

猜你喜欢

转载自blog.csdn.net/qq_24313635/article/details/81877671