我们知道Spring IOC负责创建和管理对象,那么IOC是如何低耦合的建立起它们之间的使用关系呢,有两种方式,一种是依赖注入,一种是依赖查找。
本文主要介绍依赖注入,主要有两种实现方式:
构造注入:通过有参的构造函数注入
设值注入:通过无参构造函数+setter方法注入
其实挺简单的,不用太纠结概念或者哪种方式更好,当前大部分使用设值注入的方式,只需要了解两者的用法就行了,下面用一个简单Demo了解它们的使用方法。
一边贴代码一边分析代码场景。
创建一个Spring项目
项目目录结构如下:
有两个包,iocdi包放置测试类。simpleclass包放置程序组件,其中包括计算机类,U盘类,移动硬盘类,USB接口。
现在的业务需求就是要使用计算机使用U盘存取数据,一般流程是这样,计算机中提供USB接口,U盘实现USB传输数据的功能,这样计算机就可以从U盘中读取数据了,如果计算机要从移动硬盘存取数据呢,只需要在USB接口中插入移动硬盘就行,这样就实现了计算机和存储设备的完全解耦,在计算机要实现从外部存储数据时功能时,需要依赖存储设备,这里就建立起了依赖关系,那么SpringIOC如何实现这种依赖关系呢。
Computer类代码
有一个接口变量,一个set或构造方法设定接口的值,决定插入的是哪种设备。
我们随意选择一个注入方式,但是要和后面的配置文件相对应。
package com.hnust.simpleclass;
public class Compupter {
//定义USB接口变量
private USB usb;
//设值注入方式
public void setUsb(USB usb) {
this.usb = usb;
}
/*
//构造注入方式
public Compupter(USB usb){
this.usb= usb;
}
*/
public void readData(){
usb.useUSB();
System.out.println("计算机读取数据....");
}
}
移动硬盘类代码
很简单,实现接口方法就行,表示移动硬盘具有USB接口功能
package com.hnust.simpleclass;
public class MoveDisk implements USB {
@Override
public void useUSB() {
System.out.println("移动硬盘插入USB接口");
}
}
U盘类
package com.hnust.simpleclass;
public class UDisk implements USB {
@Override
public void useUSB() {
System.out.println("U盘插入USB接口");
}
}
USB接口代码
package com.hnust.simpleclass;
public interface USB {
public void useUSB();
}
在spring-config.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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--把类对象都交给Spring管理-->
<!--Computer-->
<bean id="cpid" class="com.hnust.simpleclass.Compupter" >
<!--设置接口变量值(设值注入方式)-->
<property name="usb" ref="movedid"></property>
<!--设置接口变量值(构造注入方式)-->
<!--
<constructor-arg ref="upid"></constructor-arg>
-->
</bean>
<!--U盘-->
<bean id="upid" class="com.hnust.simpleclass.UDisk"></bean>
<!--移动硬盘-->
<bean id="movedid" class="com.hnust.simpleclass.MoveDisk"></bean>
</beans>
最后在测试类中测试代码:
TestIoCDI类
package com.hnust.iocdi;
import com.hnust.simpleclass.Compupter;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestIoCDI {
@Test
public void test1(){
ApplicationContext atc = new ClassPathXmlApplicationContext("spring-config.xml");
Compupter cp =atc.getBean("cpid",Compupter.class);
cp.readData();
}
}
实验结果:
如果我们想使用U盘,仅仅需要改变xml文件中computer的引用属性就行
更改后如下
总的来说,设值注入使用比较多,稍微直观一点,区别是不大的,就像eclipse和IDEA一样,习惯用哪个就哪个,另外还有一种接口注入的方式,现在Spring好像不支持了,所以就没有再讨论。
通过这个Demo,更加明白了通过Spring容器来管理对象的方便性,大大降低了组件对象之间的耦合度,当需求改变时,我们根本不需要更改业务组件的代码,只需要更改配置文件就行了。