本篇文章主要对 Spring 框架中的核心功能之一控制反转 (IOC,Inversion of Control)进行介绍,采用理论 + 实战的方式给大家阐述其中的原理以及明确需要注意的地方。

控制反转

通俗的讲,控制反转是一种思想,也是工程设计的一种原则,通过控制反转可以将对象的一部分控制权转移到容器(例如 Spring 容器)中,由容器帮我们控制创建对象,我们只需要在上下文中进行配置即可,配置的过程其实就是创建对象的过程。

其思想是:反转资源获取的方向。传统的资源查找的方向是要求组件向容器发起请求查找资源,同时容器返回资源。而采用 IoC 之后,容器会主动的将资源推送给它所管理的组件,组件所要做的就是选择一种合适的方式来接收资源。

而 DI(Denpendency Injection)是 IoC 的另一种表述方式,即组件以一些预先定义好的方式(例如 setter 方法)接收来自容器的资源注入

此外还可以用构造函数的方式注入

这种实现方式有什么好处呢?

首先,在传统的程序设计中,我们想要使用某个对象就需要 new 一个对象,创建对象的实例,这是我们主动创建的过程,而引入 IoC 之后,我们将这个创建对象的过程交给容器去做,由容器去控制对象的创建,当然也可以注入依赖对象,而这个过程是对象被动的接受依赖对象的。这里的容器就是我们正在学习的 Spring,它可以创建对象的实例,当我们需要对象时,直接在 Spring 容器中获得即可,直接去拿就好了。

如何拿到呢?

这时就需要用到上下文配置文件了,也就是我们常说的.xml配置文件,我们只需要在配置文件中将指定的实现类的路径名(全限定名)配置到 xml 文件中即可。

你看,通过这种方式可以很好的将创建对象的过程与我们主业务进行很好的分离,更好的降低耦合度,因为我们让 IoC 容器帮助我们去找对象并将相应的依赖注入到对象中,这时我们就不需要再主动去创建对象了。简单点说,就是以后需要写 new 的地方,我们都可以交给 IoC 容器去做,在这里也就是让 Spring 去做就可以了。

当然,这个地方配合依赖注入(DI,Dependency Injection) 来讲可能会好一点,不过没关系,博主将通过一个简单的小例子来让你明白控制反转的具体操作时什么样子的。

IoC 简单案例

在进行编码之前,我们需要一些准备工作,如环境配置说明、导入相应 jar 包、创建目标类等等,下面我们一步一步来做。

1.1 环境说明

以下声明了所有使用的编码环境,已经确定能够在该环境下进行所有的编码测试等,关于 jar 包,我们用到的时候在说。

  • JDK:11
  • 软件:IDEA 2021.2.1
  • 操作系统:Windows 10

1.2 导入相应 jar 包

这里的 jar 暂时用到的是 4+1,即 4 个核心(core、beans、beans、expression)和 1 个依赖(commons.logging),这些包你可以在官网下载。如下所示:

  • spring-core-3.2.0.RELEASE.jar
  • spring-beans-3.2.0.RELEASE.jar
  • spring-beans-3.2.0.RELEASE.jar
  • spring-expression-3.2.0.RELEASE.jar
  • com.springsource.org.apache.commons.logging-1.1.1.jar

1.3 利用 Maven 快速配置 Spring 开发环境

详细方法:Click Here

1.4 编写目标接口与实现类

我们在这里创建一个 UserService 接口,然后再创建它的一个实现类 UserServiceImpl,类里面由一个添加用户的方法 save(),然后方法里面输出一条语句即可。如下所示:

// UserService.java
public interface UserService {
public void save();
}
// UserServiceImpl.java
public class UserServiceimpl implements UserService { public void save() {
System.out.println("ioc...save");
}
}

1.5 编写测试类

然后我们再写一个测试类,用于对目标类进行测试,如下所示:

// SpringTest.java
public class SpringTest {
@Test
public void test1() {
// 之前开发时使用的方式: new
UserService userService = new UserServiceimpl();
userService.save();
}
}

这时运行测试类就得到了输出语句。你可以看到,在测试类中,我们使用以前的方法 new 了一个对象,然后调用了 addUser() 方法,最后将输出语句打印。这显然不是我们目的,我们要实现的是用 Spring 进行 IoC 后,得到同样的效果。

1.6 编写配置文件

下面就开始创建一个配置文件,我们暂且将其命名为 bean.xml(开发中一般将其命名为 applicationContext.xml)。配置文件一般放置于 src 目录下,如下所示:

<!-- bean.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"> <!-- 配置service-->
<bean id="userServiceId" class="com.my.a_ioc.UserServiceImpl"></bean> </beans>

<beans> 标签中的像网址一样的链接表示 schema 约束(模式约束),由于我们要使用到 <bean> 标签,该标签可以帮助我们配置需要创建的对象,所以这里应该将其添加进来。接下来你可以看到在 <bean> 标签中有两个属性,其中 id 是用于从 Spring 容器中获得实例的,class 表示创建实例的全限定名,即包名+类名

bean.xml 配置文件写好以后,我们需要再编写一个测试类去测试它,这个测试类将演示如何从 Spring 容器中获取实例,如下所示:

@Test
public void Test2() {
//1、获得容器
String xmlPath = "src/main/resources/bean.xml";
// File Not Find?
//ApplicationContext app = new ClassPathXmlApplicationContext(xmlPath);
ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
//2、获得内容,不需要自己new,直接从spring容器中获取: getBean 方法
UserService userService = (UserService) app.getBean("userService");
userService.save();
}

首先要指定bean.xml文件的路径,这里可以右击配置文件,选择Copy Qualified Name即可,然后将com之前的部分删掉。这里通过ClassPathXmlApplicationContext加载bean.xml文件,返回一个ApplicationContext对象,此过程实例化一个 IoC 容器。

然后通过getBean方法获取配置的bean,参数userServiceId与之前在bean.xml文件中的id是相同的。由于其返回的类型是Object,所以在这里我们将其强转成UserService类型的,最后调用addUser()方法即可。输出结果与之前实现的方法相同。

2.总结

至此,一个简单的 IoC 示例就完成了。让我们再梳理一下 IoC 容器是如何工作的。

首先是配置文件的准备,在配置文件中声明bean,为bean配置元数据,例如:idclass,然后 IoC 容器会对配置文件中的元数据进行解析,得到元数据后进行实例化、配置及组装bean操作,最后在测试类中实例化容器,获取需要的bean。主要的过程是对bean的定义以及元数据的配置。

如果你认为文章有错误或者描述不准确的话,请与我联系,谢谢!。另外,你还可以参考下面的链接进一步加深对 IoC 的理解。

参考

Spring 学习笔记(3)控制反转 IoC的更多相关文章

  1. Spring学习笔记——01 控制反转

    想一下之前学的Java,如果某个类需要引用某个对象,则需要手动new一个出来.这样带来的一个问题就是,若被引用的类发生改动或被删除,则引用它的所有类都会报错.因为两个类耦合在一起了.解决的办法就是不由 ...

  2. Spring.NET学习笔记1——控制反转(基础篇)

    在学习Spring.NET这个控制反转(IoC)和面向切面(AOP)的容器框架之前,我们先来看一下什么是控制反转(IoC). 控制反转(Inversion of Control,英文缩写为IoC),也 ...

  3. Spring学习笔记(4)——IoC学习

    IoC理论的背景我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 图1:软件系统中耦合的对象 如果我们打开机械式手表 ...

  4. Spring学习笔记(5)——IoC再度学习

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  5. spring学习总结一----控制反转与依赖注入

    spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转 ...

  6. Spring学习笔记之基础、IOC、DI(1)

    0.0 Spring基本特性 Spring是一个开源框架:是基于Core来架构多层JavaEE系统 1.0 IOC 控制反转:把对象的创建过程交给spring容器来做. 1.1 application ...

  7. Spring基础(一)_控制反转(IOC)

    Spring-IOC 1.简述 1.1 依赖注入DI 现实开发中,每一个应用都会由两个或多个类组成,这些类之间相互协作完成特定的业务逻辑.根据传统做法,每个对象负责管理与自己协作的对象的引用(也就是, ...

  8. Spring 学习笔记(二)—— IOC 容器(BeanFactory)

    使用Spring IoC容器后,容器会自动对被管理对象进行初始化并完成对象之间的依赖关系的维护,在被管理对象中无须调用Spring的API. 为了实现IoC功能,Spring提供了两个访问接口: or ...

  9. Spring学习笔记(6)——IoC的三种注入方式

    1.接口注入(不推荐) 2.构造器注入(死的应用) 3.getter,setter方式注入(比较常用) Type1 接口注入 我们常常借助接口来将调用者与实现者分离.如: public class C ...

  10. 一、Spring的控制反转(IOC)学习

    一.控制反转 1.什么是控制反转? 控制反转(Inversion of Control,缩写为IoC),是面向对象中的一种设计原则,可以用来减低计算机代码之间的耦合度.其中最常见的方式叫做依赖注入(D ...

随机推荐

  1. Modbus转PROFIBUS DP 通信网关-应用案例

    针对西门子S7系列的PLC,通用串口/PROFIBUS-DP网关(PM-160)为建立西门子PLC与现场RS232/485设备的连接提供了理想解决方案

  2. 飞码LowCode前端技术之画布的设计

    简介 本章节从精准定位.分层设计.异步组件.拖拽四个方面分析飞码画布设计. 一.精准定位设计 飞码画布是一个套件,可对外提供画布能力.精准定位有两种情况,一是目标组件无子组件,而是目标组件有子组件. ...

  3. win32 API 文件夹操作函数整理

    常用操作文件目录的函数 1. CreateDirectory 创建文件夹 原型: BOOL CreateDirectory( LPCTSTR lpPathName, LPSECURITY_ATTRIB ...

  4. Aiganize微信小程序开发手册二代

    根据此表格, 现有三个模块: 活动模块 聊天模块 影子模块 现活动模块交与:赵坤亮.郝文章做 现聊天模块与用户信息交与:葛方杰.陈金鹏做影子模块待定,现做完那两块,已经有不错的用户体验了.

  5. 最小生成树(Prim、Kruskal)

    MST 引入 现在有一个连通图,他有\(N\)个节点,\(M\)条边 当我们砍掉一些边时,它会变成一棵树,其剩下的边权之和即为这棵树的权,当剩下的权值最小时,称这棵树为此图的最小生成树,即MST 模版 ...

  6. SQL执行insert into后返回主键ID

    1 select @@identity 2 select SCOPE_IDENTITY() 3 select IDENT_CURRENT('table') 注解:@@IDENTITY 返回当前会话的所 ...

  7. 江西财经大学第一届程序设计竞赛 I 题 小P和小Q

    题目链接:https://www.nowcoder.com/acm/contest/115/I 这题目要注意的是!!!pow函数前强制类型转换一定要float !!!一定要是float,double不 ...

  8. django模型不应该作为参数传递给task

    Django 模型对象.它们不应该作为任务的参数传递.当任务运行时从数据库重新获取对象几乎总是更好,因为使用旧数据可能会导致竞争条件. 想象一下以下场景,您有一篇文章和一个自动扩展其中一些缩写的任务: ...

  9. 【2016】开机出现 system32\config\system,代码:0xc00000e9解决方法

    这是16年刚工作时写的笔记,也带来这里做个记录吧.实际工作这几年里也时不时会遇到,大多数和非正常关机有关系 今天早上,就在刚才,一个同事的电脑开不了机了,开机提示的是system32\config\s ...

  10. 华企盾DSC服务器无法启动常见处理方法

    先查看<服务问题判断>文档.常见的 1.授权已经过期--需延长授权 2.ERR_BASE64 – 机器码变更 3.不能在该计算机上使用该数据库,需要解锁才可以--打开服务器配置解锁数据库 ...