Spring 的核心思想 IoC 和 AOP

166 阅读4分钟

IoC 和 AOP 偏向于理论化, 在 Spring 之前就已经存在了。Spring 在技术层面把这两个层面做了非常好的实现。

IoC

什么是 IoC

IoC的全称是 Inversion Of Control 即控制反转与反转控制的意思。主要描述的是 Java 开发领域对象的创建和管理的问题。

传统的开发方式,比如类 A 依赖于 类 B,往往会在类 A 中 new 一个 B 的对象。但是在 IoC 下,我们不需要自己去 new 一个 B 的对象了,而是由 IoC 容器(Spring 框架)去帮助我们实例化这样一个对象并且管理它,我们从 IoC 容器中获取即可。

为什么叫控制反转

首先我把“控制反转”这个词拆解成两个词,一个是控制,另一个是反转。

控制:指的是对象创建的权力(实例化、管理)

反转:控制权交给了外部环境了(交给了 Spring 框架和 IoC 容器)

在没有 IoC 容器下,我们如何处理依赖关系的?如下图:

在由 IoC 容器的情况下,我们如何处理依赖关系的?如下图:

IoC 解决了什么问题

在上一篇中,我们说到 IoC 解决的是对象之间的耦合问题。

那么如何理解这句话呢?

我们知道 Java 代码其实是分层开发的,这里就以 service 层和 dao 层之间的调用举例:

假设 Dao 层,有一个 UserDao 及其实现类:

  • 接口:UserDao
  • 实现类:UserDaoImpl

假设 Service 层,有两个 Service (如下)都需要调用 Dao 层的 UserDao

  • 接口:UserService、OrderService
  • 实现类:UserServiceImpl、OrderServiceImpl

此时如果 UserDao 新增加了一个实现类 UserDaoNewImpl,而 UserService 需要用到 UserDaoNewImpl,此时就需要修改 Service 层相关的代码,此种 Service 和 Dao 耦合度太高,一个发生变化,另一个必须得发生变化,如果方法多的情况下,会很麻烦。

有了 AOP 思想后,只需要声明需要使用得 Dao 层接口,这样就变成了面向接口开发了,具体的实现类由 AOP 动态代理去实现。

DI

DI 的全称是 Dependency Injection 依赖注入的意思。

什么是 DI

IoC 和 DI 其实描述的是同一件事,只不过站在了不同的角度去描述了对象实例化以及依赖关系的维护。

IoC 是站在对象的角度:将对象的实例化及管理的权力交给了容器(反转给了容器)。

DI 是站在容器的角度:容器会把对象依赖的其它对象注入进去(比如:A 对象在实例化的过程中声明了 B 对象的一个属性,那么容器就会把 B 对象注入给 A)。

所以这就是 IoC 和 DI 的区别。

AOP

AOP 全称是 Aspect Oriented Programming 即面向切面编程/面向方面编程的意思。

什么是 AOP

说到 AOP ,我们必须得从 OOP 说起,我们可以把 AOP 看成是 OOP 的一个延续。

我们知道 OOP 有三大特征,分别是:封装、继承和多态。

OOP 其实是一种垂直继承体系,如下图:

OOP 编程思想可以解决大部分的重复代码问题,但是有些情况是处理不了的,比如:在 Animal 中的多个方法中相同的位置上出现了重复代码(日志、性能监控、事务等),OOP 就解决不了。在这里我们需要提到一个词:横切逻辑代码。

横切逻辑代码

横切逻辑代码:在多个纵向(顺序)流程中出现的相同子流程代码,我们称之为横切逻辑代码。

横切逻辑代码的使用场景:一般都是事务控制、权限校验、日志打印等。

横切逻辑代码本身存在什么问题:

  • 代码重复
  • 横切逻辑代码与业务代码混杂在一起,代码臃肿,不方便维护

AOP 的出现就可以解决这种问题。但是代码拆分容易,那么在不改变原有业务逻辑的情况下,如何做到悄无声息的把横切逻辑代码应用到原有的业务逻辑中,达到和原来一样的效果,这个是很困难的。

所以 AOP 解决的问题是:在不改变原有业务逻辑的情况下,增强横切逻辑代码,从根本上进行解耦,避免恒切逻辑代码重复。

什么是面向切面编程

切:指的是横切逻辑,原有的业务逻辑我们不能动,只能操作横切逻辑代码,所以是面向横切逻辑。

面:横切逻辑代码往往是要影响很多个方法的,每一个方法如同一个点,多个点构成一个面,这就是面的概念了。

参考内容:spring.io/projects/sp…