《我想進大廠》之Spring奪命連環10問

1.說說Spring 裏用到了哪些設計模式?

單例模式:Spring 中的 Bean 默認狀況下都是單例的。無需多說。數據庫

工廠模式:工廠模式主要是經過 BeanFactory 和 ApplicationContext 來生產 Bean 對象。編程

代理模式:最多見的 AOP 的實現方式就是經過代理來實現,Spring主要是使用 JDK 動態代理和 CGLIB 代理。設計模式

模板方法模式:主要是一些對數據庫操做的類用到,好比 JdbcTemplate、JpaTemplate,由於查詢數據庫的創建鏈接、執行查詢、關閉鏈接幾個過程,很是適用於模板方法。緩存

2.談談你對IOC 和 AOP 的理解?他們的實現原理是什麼?

IOC 叫作控制反轉,指的是經過Spring來管理對象的建立、配置和生命週期,這樣至關於把控制權交給了Spring,不須要人工來管理對象之間複雜的依賴關係,這樣作的好處就是解耦。在Spring裏面,主要提供了 BeanFactory 和 ApplicationContext 兩種 IOC 容器,經過他們來實現對 Bean 的管理。微信

AOP 叫作面向切面編程,他是一個編程範式,目的就是提升代碼的模塊性。Srping AOP 基於動態代理的方式實現,若是是實現了接口的話就會使用 JDK 動態代理,反之則使用 CGLIB 代理,Spring中 AOP 的應用主要體如今 事務、日誌、異常處理等方面,經過在代碼的先後作一些加強處理,能夠實現對業務邏輯的隔離,提升代碼的模塊化能力,同時也是解耦。Spring主要提供了 Aspect 切面、JoinPoint 鏈接點、PointCut 切入點、Advice 加強等實現方式。網絡

3. JDK 動態代理和 CGLIB 代理有什麼區別?

JDK 動態代理主要是針對類實現了某個接口,AOP 則會使用 JDK 動態代理。他基於反射的機制實現,生成一個實現一樣接口的一個代理類,而後經過重寫方法的方式,實現對代碼的加強。多線程

而若是某個類沒有實現接口,AOP 則會使用 CGLIB 代理。他的底層原理是基於 asm 第三方框架,經過修改字節碼生成成成一個子類,而後重寫父類的方法,實現對代碼的加強。框架

4. Spring AOP 和 AspectJ AOP 有什麼區別?

Spring AOP 基於動態代理實現,屬於運行時加強。編輯器

AspectJ 則屬於編譯時加強,主要有3種方式:模塊化

  1. 編譯時織入:指的是加強的代碼和源代碼咱們都有,直接使用 AspectJ 編譯器編譯就好了,編譯以後生成一個新的類,他也會做爲一個正常的 Java 類裝載到JVM。
  2. 編譯後織入:指的是代碼已經被編譯成 class 文件或者已經打成 jar 包,這時候要加強的話,就是編譯後織入,好比你依賴了第三方的類庫,又想對他加強的話,就能夠經過這種方式。

  1. 加載時織入:指的是在 JVM 加載類的時候進行織入。

總結下來的話,就是 Spring AOP 只能在運行時織入,不須要單獨編譯,性能相比 AspectJ 編譯織入的方式慢,而 AspectJ 只支持編譯先後和類加載時織入,性能更好,功能更增強大。

5. FactoryBean 和 BeanFactory有什麼區別?

BeanFactory 是 Bean 的工廠, ApplicationContext 的父類,IOC 容器的核心,負責生產和管理 Bean 對象。

FactoryBean 是 Bean,能夠經過實現 FactoryBean 接口定製實例化 Bean 的邏輯,經過代理一個Bean對象,對方法先後作一些操做。

6.SpringBean的生命週期說說?

SpringBean 生命週期簡單歸納爲4個階段:

  1. 實例化,建立一個Bean對象

  2. 填充屬性,爲屬性賦值

  3. 初始化

    • 若是實現了xxxAware接口,經過不一樣類型的Aware接口拿到Spring容器的資源
    • 若是實現了BeanPostProcessor接口,則會回調該接口的postProcessBeforeInitialzationpostProcessAfterInitialization方法
    • 若是配置了init-method方法,則會執行init-method配置的方法
  4. 銷燬

    • 容器關閉後,若是Bean實現了DisposableBean接口,則會回調該接口的destroy方法
    • 若是配置了destroy-method方法,則會執行destroy-method配置的方法

7.Spring是怎麼解決循環依賴的?

首先,Spring 解決循環依賴有兩個前提條件:

  1. 不全是構造器方式的循環依賴
  2. 必須是單例

基於上面的問題,咱們知道Bean的生命週期,本質上解決循環依賴的問題就是三級緩存,經過三級緩存提早拿到未初始化的對象。

第一級緩存:用來保存實例化、初始化都完成的對象

第二級緩存:用來保存實例化完成,可是未初始化完成的對象

第三級緩存:用來保存一個對象工廠,提供一個匿名內部類,用於建立二級緩存中的對象

假設一個簡單的循環依賴場景,A、B互相依賴。

A對象的建立過程:

  1. 建立對象A,實例化的時候把A對象工廠放入三級緩存

  1. A注入屬性時,發現依賴B,轉而去實例化B
  2. 一樣建立對象B,注入屬性時發現依賴A,一次從一級到三級緩存查詢A,從三級緩存經過對象工廠拿到A,把A放入二級緩存,同時刪除三級緩存中的A,此時,B已經實例化而且初始化完成,把B放入一級緩存。

  1. 接着繼續建立A,順利從一級緩存拿到實例化且初始化完成的B對象,A對象建立也完成,刪除二級緩存中的A,同時把A放入一級緩存
  2. 最後,一級緩存中保存着實例化、初始化都完成的A、B對象

所以,因爲把實例化和初始化的流程分開了,因此若是都是用構造器的話,就無法分離這個操做,因此都是構造器的話就沒法解決循環依賴的問題了。

8. 爲何要三級緩存?二級不行嗎?

不能夠,主要是爲了生成代理對象。

由於三級緩存中放的是生成具體對象的匿名內部類,他能夠生成代理對象,也能夠是普通的實例對象。

使用三級緩存主要是爲了保證無論何時使用的都是一個對象。

假設只有二級緩存的狀況,往二級緩存中放的顯示一個普通的Bean對象,BeanPostProcessor去生成代理對象以後,覆蓋掉二級緩存中的普通Bean對象,那麼多線程環境下可能取到的對象就不一致了。

9.Spring事務傳播機制有哪些?

  1. PROPAGATION_REQUIRED:若是當前沒有事務,就建立一個新事務,若是當前存在事務,就加入該事務,這也是一般咱們的默認選擇。
  2. PROPAGATION_REQUIRES_NEW:建立新事務,不管當前存不存在事務,都建立新事務。
  3. PROPAGATION_NESTED:若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則按REQUIRED屬性執行。
  4. PROPAGATION_NOT_SUPPORTED:以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。
  5. PROPAGATION_NEVER:以非事務方式執行,若是當前存在事務,則拋出異常。
  6. PROPAGATION_MANDATORY:支持當前事務,若是當前存在事務,就加入該事務,若是當前不存在事務,就拋出異常。
  7. PROPAGATION_SUPPORTS:支持當前事務,若是當前存在事務,就加入該事務,若是當前不存在事務,就以非事務執行。‘

10.最後,說說Spring Boot 啓動流程吧?

這個流程,網上一搜基本都是這張圖了,我也不想再畫一遍了。那其實主要的流程就幾個步驟:

  1. 準備環境,根據不一樣的環境建立不一樣的Environment
  2. 準備、加載上下文,爲不一樣的環境選擇不一樣的Spring Context,而後加載資源,配置Bean
  3. 初始化,這個階段刷新Spring Context,啓動應用
  4. 最後結束流程

圖片來源網絡,若有侵權請聯繫我刪除圖片來源網絡,若有侵權請聯繫我刪除

另外,讀者羣已經開通,講真的,就算不說話,在羣裏也能學到很多東西呢。加我微信,備註進羣,我拉你!

- END -

相關文章
相關標籤/搜索