Spring-理解依赖注入

以配置文件的形式管理java实例的协作方式--  这种方式叫依赖注入也叫控制反转

    传统模式下,当某个java实例(调用者)需要调用另一个java实例(被依赖对象)的方法时,有如下两种方式:

(1)调用者创建被依赖对象的实例,再调用该实例的方法

缺点:new的形式调用被依赖对象的构造器,导致调用者与被依赖对象实现类的硬编码耦合。不利于维护

(2)工厂模式:通过定位到被依赖对象的工厂,通过工厂获取被依赖对象。

优点:1.面向接口编程 2. 不用由调用者创建对象,交由工厂创建被依赖对象的实例

缺点:调用者需要主动通过工厂去获取依赖对象,造成了调用组件与被依赖对象工厂的耦合。

  引入Spring框架:无需主动获取被依赖对象,被动接受Spring容器为调用者的成员变量赋值,调用者获取被依赖对象从主动变成被动接受---这就叫控制反转(从调用者的角度看)。

从Spring的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,,为调用者注入它依赖的实例--这就叫依赖注入

小结:依赖注入和控制反转含义差不多(主要看从不同的角度去看)

依赖注入的两种方式:

(1)设值注入

   loc容器通过成员变量的setter注入被依赖对象。

示例如下:

Spring推荐面向接口编程

定义两个接口

public interface Person {
	//使用斧子
	public void useAxe();
}

public interface Axe {
	public String chop();
}

Person实现类

public class Chinese implements Person{
	private Axe axe;
	public void setAxe(Axe axe){
		this.axe = axe;
	}

	@Override
	public void useAxe() {
		// TODO Auto-generated method stub
		System.out.println(axe.chop());
	}

}

Axe实现类

public class StoneAxe implements Axe{
	
	@Override
	public String chop() {
		// TODO Auto-generated method stub
		//System.out.println("钢斧砍柴");
		return "钢斧砍柴";
	}
	
}
Chinese无需主动调用Axe实例,Axe实例由Spring容器被动注入,这种实现通过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"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 配置chinese实例 -->
<bean id="chinese" class="com.Chinese">
	<property name="axe" ref="stoneAxe"/>
</bean>
<bean id="stoneAxe" class="com.StoneAxe">
</bean></beans>

id:bean的唯一标识,程序通过id来访问bean

class:bean的实现类

Spring会检测<property>的定义,在调用构造器创建bean实例后,调用对应的setter方法为bean成员变量注入值。

测试:

public class beanTest {
	public static void main(String[] args) {
		//(1) 创建Spring容器
		ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
		//(2)获取bean实例
		Person p = ctx.getBean("chinese",Person.class);
		p.useAxe();
	}
}

结果:钢斧砍柴。

假设:后期出现修改,不在想使用钢斧,想使用金刚斧

金刚斧的实现类

public class SteelAxe implements Axe{

	@Override
	public String chop() {
		// TODO Auto-generated method stub
		return "金刚斧砍柴真快";
	}
	
}
这时候需要修改的就是配置文件,重新定义Axe实例,修改chinese的传入参数
 
<!-- 配置chinese实例 -->
<bean id="chinese" class="com.Chinese">
	<property name="axe" ref="steelAxe"/>
</bean>
<bean id="steelAxe" class="com.SteelAxe">
</bean></beans>

这时候结果发生改变:
金刚斧砍柴真快。

结论:如此看来,chinese实现类与Axe实现类没有关系,只是借口的耦合,保证了chinese实例与axe实例的松耦合。
Spring根据配置文件或者注解来管理bean的实现类和依赖关系,利用反射创建实例,并注入依赖关系。
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

(2)构造注入

   在构造实例时就完成了依赖关系的初始化,利用构造器来设置依赖关系。

示例:

通过带参数的构造器注入所依赖的bean示例

public class Chinese implements Person{
	private Axe axe;
	//采用构造的方式注入
	public Chinese(Axe axe){
		this.axe = axe;
	}

	@Override
	public void useAxe() {
		// TODO Auto-generated method stub
		System.out.println(axe.chop());
	}

}
配置文件:

<!-- 配置chinese实例 -->
<bean id="chinese" class="com.Chinese">
	<constructor-arg ref="steelAxe"/>
</bean>
<bean id="steelAxe" class="com.SteelAxe">
</bean></beans>

<constructor-arg>指定构造器参数,通过index属性设定以第几个构造参数传入(0为第一个)

设值注入和构造注入的比较

尽量采用设值注入为主,构造注入为辅的注入策略。

对于依赖关系无需变化的注入------构造注入

依赖关系复杂------------设值注入


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值