“本文已经收录进个人 79K Star 的 Java 开源项目 JavaGuide:github.com/Snailclimb/… (「Java学习+面试指南」一份涵盖大部分Java程序员所须要掌握的核心知识。)html
相关阅读:完结撒花!Github接近80K点赞的Java面试指南来啦!git
本文为读者投稿!程序员
这篇文章会从下面从如下几个问题展开对 IoC & AOP 的解释github
首先声明:IoC & AOP 不是 Spring 提出来的,它们在 Spring 以前其实已经存在了,只不过当时更加偏向于理论。Spring 在技术层次将这两个思想进行了很好的实现。web
IoC (Inversion of control )控制反转/反转控制。它是一种思想不是一个技术实现。描述的是:Java 开发领域对象的建立以及管理的问题。面试
例如:现有类 A 依赖于类 B编程
从以上两种开发方式的对比来看:咱们 “丧失了一个权力” (建立、管理对象的权力),从而也获得了一个好处(不用再考虑对象的建立、管理等一系列的事情)框架
控制 :指的是对象建立(实例化、管理)的权力编辑器
反转 :控制权交给外部环境(Spring 框架、IoC 容器)ide
IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。这样有什么好处呢?
例如:现有一个针对 User 的操做,利用 Service 和 Dao 两层结构进行开发
在没有使用 IoC 思想的状况下,Service 层想要使用 Dao 层的具体实现的话,须要经过 new 关键字在UserServiceImpl
中手动 new 出 IUserDao
的具体实现类 UserDaoImpl
(不能直接 new 接口类)。
很完美,这种方式也是能够实现的,可是咱们想象一下以下场景:
开发过程当中忽然接到一个新的需求,针对对IUserDao
接口开发出另外一个具体实现类。由于 Server 层依赖了IUserDao
的具体实现,因此咱们须要修改UserServiceImpl
中 new 的对象。若是只有一个类引用了IUserDao
的具体实现,可能以为还好,修改起来也不是很费力气,可是若是有许许多多的地方都引用了IUserDao
的具体实现的话,一旦须要更换IUserDao
的实现方式,那修改起来将会很是的头疼。
使用 IoC 的思想,咱们将对象的控制权(建立、管理)交有 IoC 容器去管理,咱们在使用的时候直接向 IoC 容器 “要” 就能够了
IoC(Inverse of Control:控制反转)是一种设计思想 或者说是某种模式。这个设计思想就是 将本来在程序中手动建立对象的控制权,交由 Spring 框架来管理。 IoC 在其余语言中也有应用,并不是 Spring 特有。IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各类对象。
IoC 最多见以及最合理的实现方式叫作依赖注入(Dependency Injection,简称 DI)。
而且,老马(Martin Fowler)在一篇文章中提到将 IoC 更名为 DI,原文以下,原文地址:https://martinfowler.com/articles/injection.html 。
老马的大概意思是 IoC 太广泛而且不表意,不少人会所以而迷惑,因此,使用 DI 来精确指名这个模式比较好。
AOP:Aspect oriented programming 面向切面编程,AOP 是 OOP(面向对象编程)的一种延续。
下面咱们先看一个 OOP 的例子。
例如:现有三个类,Horse
、Pig
、Dog
,这三个类中都有 eat 和 run 两个方法。
经过 OOP 思想中的继承,咱们能够提取出一个 Animal 的父类,而后将 eat 和 run 方法放入父类中,Horse
、Pig
、Dog
经过继承Animal
类便可自动得到 eat()
和 run()
方法。这样将会少些不少重复的代码。
OOP 编程思想能够解决大部分的代码重复问题。可是有一些问题是处理不了的。好比在父类 Animal 中的多个方法的相同位置出现了重复的代码,OOP 就解决不了。
/** * 动物父类 */ 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("执行时长:" + (System.currentTimeMillis() - start)/1000f + "s"); } public void run() { // 性能监控代码 long start = System.currentTimeMillis(); // 业务逻辑代码 System.out.println("I can run..."); // 性能监控代码 System.out.println("执行时长:" + (System.currentTimeMillis() - start)/1000f + "s"); } } 复制代码
这部分重复的代码,通常统称为 横切逻辑代码。
横切逻辑代码存在的问题:
AOP 就是用来解决这些问题的
AOP 另辟蹊径,提出横向抽取机制,将横切逻辑代码和业务逻辑代码分离
代码拆分比较容易,难的是如何在不改变原有业务逻辑的状况下,悄无声息的将横向逻辑代码应用到原有的业务逻辑中,达到和原来同样的效果。
经过上面的分析能够发现,AOP 主要用来解决:在不改变原有业务逻辑的状况下,加强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。
切 :指的是横切逻辑,原有业务逻辑代码不动,只能操做横切逻辑代码,因此面向横切逻辑
面 :横切逻辑代码每每要影响的是不少个方法,每一个方法如同一个点,多个点构成一个面。这里有一个面的概念
本文使用 mdnice 排版