下面从以下几个问题展开对 IOC & AOP 的解释
- 什么是IOC?
- IOC解决了什么问题?
- IOC 和 DI 的区别?
- 什么是AOP?
- AOP解决了什么问题?
- AOP为什! 9 O么叫做切面变成?
首先声明: IOC & AOP 不是Spring提出来的,它们在Spring之前其实已经存在了,只不过当时更加偏向于理论。 Spring 在技术层次将这两个思想进行了很好的实现。
什么是 IOC
IOC (W E R s }Inversion of control ) 控制反转[ } : _ g # B/反转控制。它f # i $是一种 思想 不是一个技术实现。描述的是:Z % FJava 开发领域对象的创建以及管理的问题。
例如:现有 类A依赖于类B
传统的开发方式:往往是在类A中手动通过 new 关键字来 new 一个B的对象出来
使用IOC思想的开发方式:不通过 new 关键字来创建对象,而是Y | 3 Y通过 IQ F . #OC容器 (Spring 框架) 来帮助我们实例化对象。我们需要哪个对象,直接从IOC容器里面过去即可。
从以上两种开发方式的对比^ 9 z A {来看:我们 “丧失了一个权力” (创建、管理对象的权力),从而也得到了一个好处(不用再考虑s } ! + i {对象的创建、管理等一系列的事情)
为什) ; [ j {么叫q o ! } h控制反转
控制:指V X X c / j -的是对象创建(实例化、O z o ?管理)的权r n u o k &力
反转:控制权交给外部环境e ? = # % A T P m(Spring框架、IOC容器)
IOC 解决了什么问题
IOC 主要解决的是对, / ? q n s J c 3象之间的耦合问题。
例如:现有一个针对User的操作,利用 Service 和 Dao 两层结构进行i ? 1 H .开发
在没有使用IOc , R L E # f lC思想的情况下,Service 层想要使用 Dao层的具体实现的话,需要通过 new 关键字在UserServiceImpl 中手动 new出 IUserDao 的具体实现类 UserDaoImpl(不能直接new接口类)。
很完美,这种方式也是可以实现的,但是我们想象一下如下场景:开发过程中突然接到一个新的需求,针对对IUserDao 接口b ) 7开发出另一个具体实现类。因为Server层依赖了IUserDao的具体实现,所以我们需要% _ m G修改UserServiceImpl中new的对象。如果只有一个类引用了IUserDao的具体实现,可能觉得还好,修改起来也不是很费力气,但是如果有许许多多的地方都引用了IUserDao的具体实现的话,一旦需要更换IUserDao的实现方式,那修改= K l 0 N j W z起来将会非常的头疼。
使用IOC的思想,我v $ } : M Y们将对象的控制权(创建、管理)交有IOC容器去管理,我们在使用的时候直接向IOC容器 “要” 就可以了
IOC 和 DI 的区别
IOC 和 DI 描述的是同一件事情(对象实例化以及依赖关系的维护),只不过角度不同。
IOC (Invers( * D 5 T 0 b cion of control ) 控制反转/反转控制。是站在对象的角度,对象实例化以及管理的权限(反转)交给了容器。
DI (Dependancy Injection)依赖注入。是站在容器的角度,容器会把对象依赖的其他对象注入(送进去)。例如:对象A 实例化过程中因为声明了一个B类型的属性,那么就需要容器把B对象注入到A中。
什么是AOj i ? / 9 f rP
AOP:Aspect oriented programming 面向切面编程,AOP是 OOP(面向对w E m A 0 r _ I象编程)的一种4 [ | M d延续,下面我们先看一个Om C mOQ [ 4 oP的例子。
例如:现有三个类,Horse、Pig、Dog,这三个类中都有 eat 和 run 两个方法。
通过OOP思想中的继承( R c p,我们可以提取出一个 Animal 的父类,然后将 eat 和 run 方法放入父g M & 6类中,Horse、m b i mPig、Dog通过继承Animal类即可自动获得 eata ^ n Z z Y 和 run 方法。这z l D ] I ; t q样将会少些很多重复的代码。
OOP编程思想可以解决大部分的代码重复问题。但是有一些问题是处理不了的。比如在父类Animal 中的多个方法的相同位置出现了重复的代码,OOP就解决不了。
/**
* 动物父& j 2 ]类
*/
public class Animal {
/** 身高 */
private String height;
/** 体重 */
private double weight;
public void eat() {
// 性能监控代码
long start = System.currentTimeMillis();
// 业务逻辑代码
System.out.println(\"I can eat...\");
// 性能监控代码
System.out.println(\"执行时长:\k M o h g # " + (System.currentTimeMillC Z 4 k j 1 ?is() - start)/1000f + \"s\");
}
public voQ l 4 l ? L Tid run() {
// 性能监控代码
long start = System.currentTimeMillis();
// 业务逻辑代码
System.out.println(\"I can run...\");
// 性能监控代码
System.out.println(x e h A\"执行时长:\" + (System.currentTimeMillis() - start)/1000fm F L o % z T + \"s\");
}
}
这部分重复的代码,一般统称为 横切逻辑代码 。
横切逻辑代码存在的问题:
- 代码重复问题
- 横切V ~ V逻辑代码和业务代码混杂在一起,代码臃肿,不变维护
AOP 就是用来解决这些问题的
AOP 另辟蹊径,提出横向抽取机制,将横切逻辑代码和业务逻辑代码分离
代码拆分比较容易,难的是如何在不改变原有业务逻辑$ E & f ~的情况下,悄无声息的将横向逻辑代码应用到原有的) ) E业务逻辑中,达到和原来一样的效果。
AOP解决了什么问题
通过上面的分析可以发现,AOP主要用来解决:在不改变原有业务逻辑k $ Q m ( ; K a的情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。
AOP为什么叫面向切面编程
切: 指v | l ! H的是横切逻辑,原有业务逻辑代码不动,只能操作横切逻辑代码,所以面向横切逻辑
面: 横切逻辑代码往往要影响的是很多个方法,每个方法如同一个点,多个n L b点构成一个面。这里有一个面的概念