基本概念
控制反转(Inversion of Control,IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度,指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。
控制指的是控制对象的创建、销毁、属性的赋值。反转指的是在程序代码之外,由容器实现对象的创建和属性赋值,把开发人员创建对象的权限转移给了代码之外的容器。(正转:在程序代码中,由开发人员主动new创建对象)
在Spring中,就是通过IoC来对业务对象之间进行解耦合。
技术描述
Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。
采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。
实现方法
实现控制反转主要有两种方式:依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。两者的区别在于,前者是被动的接收对象,在类A的实例创建过程中即创建了依赖的B对象,通过类型或名称来判断将不同的对象注入到不同的属性中,而后者是主动索取相应类型的对象,获得依赖对象的时间也可以在代码中自由控制。
Spring实现控制反转使用的是DI,底层实现使用的是反射技术,使用反射的好处是不用导入额外的jar包。
Spring的第一个程序
在真实项目中,一般使用Maven或者Gradle部署项目,这里我们为了简单起见,直接去官网下载Spring Framework的jar包(Spring Framework下载地址),这里下载的版本是spring-framework-5.1.9.RELEASE-dist.zip,解压后的文件目录如下:
1. 新建java项目,并导入所需jar包
博主使用的IDE为IDEA,首先,新建一个简单的java工程,然后导入Spring Framework的lib目录下的几个核心jar包,以及commons-logging的jar包(不导入的话,运行会报错,应该是spring有调用到这个包的类,commons-logging下载地址),可以将单元测试Junit的jar包一起导入,方便测试(Junit-4.12下载地址),导入的jar包列表如下:
导入jar包之后,需要将jar包添加到项目中(右键点击jar包,选择Add as Library),才可以使用。
2. 定义测试服务接口和实现类
项目目录结构如下:
- SomeService.java:
public interface SomeService {
void doSome();
}
- SomeServiceImpl.java:
public class SomeServiceImpl implements SomeService{
@Override
public void doSome() {
System.out.println("---------业务处理---------");
}
}
3. 定义Spring的配置文件
在src目录下新建一个xml文件,命名为applicationContext.xml(业界通用命名),向配置文件中添加spring的约束文件,并在<bean>标签中定义要创建的对象:
<?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">
<!-- 声明bean对象(即java对象)
id:自定义对象名称
class:全限定类名
<bean>的作用等同于: SomeService someService = new com.lyj.main.service.SomeServiceImpl();
-->
<bean id="someService" class="com.lyj.main.service.SomeServiceImpl"/>
</beans>
4. 定义测试类
这里测试的是,使用Spring管理的对象,即<bean>中定义的对象。
- MyTest.java
public class MyTest {
public static void main(String[] args){
// 1. 定义配置文件路径
String configLocation = "applicationContext.xml";
// 2. 创建Spring容器对象,使用的是ApplicationContext接口
// 根据配置文件的位置不用,使用不同的实现类
// A. 配置文件放在类路径src(classPath)下——常用
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
/**
* B. 配置文件放在项目路径下(与src同级)
* ApplicationContext context = new FileSystemXmlApplicationContext(configLocation);
* C. 配置文件放在磁盘中
* ApplicationContext context = new FileSystemXmlApplicationContext("磁盘文件完整路径");
*/
// 3. 从容器获取对象
SomeService someService = (SomeService) context.getBean("someService");
// 4. 调用对象的业务方法
someService.doSome();
}
}
运行测试类后,可以看到控制台输出的结果: