面試被問了幾百遍的 IoC 和 AOP ,還在傻傻搞不清楚?

本文已經收錄進個人 79K Star 的 Java 開源項目 JavaGuide:github.com/Snailclimb/… (「Java學習+面試指南」一份涵蓋大部分Java程序員所須要掌握的核心知識。)html

相關閱讀:完結撒花!Github接近80K點讚的Java面試指南來啦!git

本文爲讀者投稿!程序員

這篇文章會從下面從如下幾個問題展開對 IoC & AOP 的解釋github

  • 什麼是 IoC?
  • IoC 解決了什麼問題?
  • IoC 和 DI 的區別?
  • 什麼是 AOP?
  • AOP 解決了什麼問題?
  • AOP 爲何叫作切面編程?

首先聲明:IoC & AOP 不是 Spring 提出來的,它們在 Spring 以前其實已經存在了,只不過當時更加偏向於理論。Spring 在技術層次將這兩個思想進行了很好的實現。web

什麼是 IoC

IoC (Inversion of control )控制反轉/反轉控制。它是一種思想不是一個技術實現。描述的是:Java 開發領域對象的建立以及管理的問題。面試

例如:現有類 A 依賴於類 B編程

  • 傳統的開發方式 :每每是在類 A 中手動經過 new 關鍵字來 new 一個 B 的對象出來
  • 使用 IoC 思想的開發方式 :不經過 new 關鍵字來建立對象,而是經過 IoC 容器(Spring 框架) 來幫助咱們實例化對象。咱們須要哪一個對象,直接從 IoC 容器裏面過去便可。

從以上兩種開發方式的對比來看:咱們 「喪失了一個權力」 (建立、管理對象的權力),從而也獲得了一個好處(不用再考慮對象的建立、管理等一系列的事情)框架

爲何叫控制反轉

控制 :指的是對象建立(實例化、管理)的權力編輯器

反轉 :控制權交給外部環境(Spring 框架、IoC 容器)ide

IoC 解決了什麼問題

IoC 的思想就是兩方之間不互相依賴,由第三方容器來管理相關資源。這樣有什麼好處呢?

  1. 對象之間的耦合度或者說依賴程度下降;
  2. 資源變的容易管理;好比你用 Spring 容器提供的話很容易就能夠實現一個單例。

例如:現有一個針對 User 的操做,利用 Service 和 Dao 兩層結構進行開發

在沒有使用 IoC 思想的狀況下,Service 層想要使用 Dao 層的具體實現的話,須要經過 new 關鍵字在UserServiceImpl 中手動 new 出 IUserDao 的具體實現類 UserDaoImpl(不能直接 new 接口類)。

很完美,這種方式也是能夠實現的,可是咱們想象一下以下場景:

開發過程當中忽然接到一個新的需求,針對對IUserDao 接口開發出另外一個具體實現類。由於 Server 層依賴了IUserDao的具體實現,因此咱們須要修改UserServiceImpl中 new 的對象。若是隻有一個類引用了IUserDao的具體實現,可能以爲還好,修改起來也不是很費力氣,可是若是有許許多多的地方都引用了IUserDao的具體實現的話,一旦須要更換IUserDao 的實現方式,那修改起來將會很是的頭疼。

img
img

使用 IoC 的思想,咱們將對象的控制權(建立、管理)交有 IoC 容器去管理,咱們在使用的時候直接向 IoC 容器 「要」 就能夠了

img
img

IoC 和 DI 別再傻傻分不清楚

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 。

img
img

老馬的大概意思是 IoC 太廣泛而且不表意,不少人會所以而迷惑,因此,使用 DI 來精確指名這個模式比較好。

什麼是 AOP

AOP:Aspect oriented programming 面向切面編程,AOP 是 OOP(面向對象編程)的一種延續。

下面咱們先看一個 OOP 的例子。

例如:現有三個類,HorsePigDog,這三個類中都有 eat 和 run 兩個方法。

經過 OOP 思想中的繼承,咱們能夠提取出一個 Animal 的父類,而後將 eat 和 run 方法放入父類中,HorsePigDog經過繼承Animal類便可自動得到 eat()run() 方法。這樣將會少些不少重複的代碼。

img
img

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");  } } 複製代碼

這部分重複的代碼,通常統稱爲 橫切邏輯代碼

img
img

橫切邏輯代碼存在的問題:

  • 代碼重複問題
  • 橫切邏輯代碼和業務代碼混雜在一塊兒,代碼臃腫,不變維護

AOP 就是用來解決這些問題的

AOP 另闢蹊徑,提出橫向抽取機制,將橫切邏輯代碼和業務邏輯代碼分離

img
img

代碼拆分比較容易,難的是如何在不改變原有業務邏輯的狀況下,悄無聲息的將橫向邏輯代碼應用到原有的業務邏輯中,達到和原來同樣的效果。

AOP 解決了什麼問題

經過上面的分析能夠發現,AOP 主要用來解決:在不改變原有業務邏輯的狀況下,加強橫切邏輯代碼,根本上解耦合,避免橫切邏輯代碼重複。

AOP 爲何叫面向切面編程

:指的是橫切邏輯,原有業務邏輯代碼不動,只能操做橫切邏輯代碼,因此面向橫切邏輯

:橫切邏輯代碼每每要影響的是不少個方法,每一個方法如同一個點,多個點構成一個面。這裏有一個面的概念

本文使用 mdnice 排版

相關文章
相關標籤/搜索