【Spring】Spring 常見問題

目錄

(1)談談自己對於 Spring IoC 和 AOP 的理解

(2)Spring AOP 和 AspectJ AOP 有什麼區別?

(3)Spring 中的 bean 的作用域有哪些?

(4)Spring 中的單例 bean 的線程安全問題了解嗎?

(5)SpringMVC 工作原理了解嗎?

(6)Spring 框架中用到了哪些設計模式?

(7)@Component 和 @Bean 的區別是什麼?


學習地址

(1)談談自己對於 Spring IoC 和 AOP 的理解

 1、IoC(Inverse of Control:控制反轉)是一種設計思想,就是 將原本在程序中手動創建對象的控制權,交由Spring框架來管理。 IoC 在其他語言中也有應用,並非 Spirng 特有。 IoC 容器是 Spring 用來實現 IoC 的載體, IoC 容器實際上就是個Map(key,value),Map 中存放的是各種對象。

  • 將對象之間的相互依賴關係交給 IOC 容器來管理,並由 IOC 容器完成對象的注入。這樣可以很大程度上簡化應用的開發,把應用從複雜的依賴關係中解放出來。 IOC 容器就像是一個工廠一樣,當我們需要創建一個對象的時候,只需要配置好配置文件/註解即可,完全不用考慮對象是如何被創建出來的。 在實際項目中一個 Service 類可能有幾百甚至上千個類作爲它的底層,假如我們需要實例化這個 Service,你可能要每次都要搞清這個 Service 所有底層類的構造函數,這可能會把人逼瘋。如果利用 IOC 的話,你只需要配置好,然後在需要的地方引用就行了,這大大增加了項目的可維護性且降低了開發難度。

Spring 時代我們一般通過 XML 文件來配置 Bean,後來開發人員覺得 XML 文件來配置不太好,於是 SpringBoot 註解配置就慢慢開始流行起來。

推薦閱讀:https://www.zhihu.com/question/23277575/answer/169698662

Spring IOC的初始化過程: 

                                 Spring IOC的初始化過程

IOC源碼閱讀:     https://javadoop.com/post/spring-ioc

2、AOP(Aspect-Oriented Programming:面向切面編程)能夠將那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任(例如事務處理、日誌管理、權限控制等)封裝起來,便於減少系統的重複代碼降低模塊間的耦合度,並有利於未來的可拓展性和可維護性

Spring AOP就是基於動態代理的,如果要代理的對象,實現了某個接口,那麼Spring AOP會使用JDK Proxy,去創建代理對象,而對於沒有實現接口的對象,就無法使用 JDK Proxy 去進行代理了,這時候Spring AOP會使用Cglib ,這時候Spring AOP會使用 Cglib 生成一個被代理對象的子類來作爲代理,如下圖所示:

                

當然你也可以使用 AspectJ ,Spring AOP 已經集成了AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。

使用 AOP 之後我們可以把一些通用功能抽象出來,在需要用到的地方直接使用即可,這樣大大簡化了代碼量。我們需要增加新功能時也方便,這樣也提高了系統擴展性。日誌功能、事務管理等等場景都用到了 AOP 

(2)Spring AOP 和 AspectJ AOP 有什麼區別?

Spring AOP 屬於運行時增強,而 AspectJ 是編譯時增強。 Spring AOP 基於代理(Proxying),而 AspectJ 基於字節碼操作(Bytecode Manipulation)。

Spring AOP 已經集成了 AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。AspectJ 相比於 Spring AOP 功能更加強大,但是 Spring AOP 相對來說更簡單,

如果我們的切面比較少,那麼兩者性能差異不大。但是,當切面太多的話,最好選擇 AspectJ ,它比Spring AOP 快很多。

(3)Spring 中的 bean 的作用域有哪些?

  • singleton : 唯一 bean 實例,Spring 中的 bean 默認都是單例的。
  • prototype : 每次請求都會創建一個新的 bean 實例。
  • request : 每一次HTTP請求都會產生一個新的bean,該bean僅在當前HTTP request內有效。
  • session : 每一次HTTP請求都會產生一個新的 bean,該bean僅在當前 HTTP session 內有效。
  • global-session:全局session作用域,僅僅在基於portlet的web應用中才有意義,Spring5已經沒有了。Portlet是能夠生成語義代碼(例如:HTML)片段的小型Java Web插件。它們基於portlet容器,可以像servlet一樣處理HTTP請求。但是,與 servlet 不同,每個 portlet 都有不同的會話

(4)Spring 中的單例 bean 的線程安全問題了解嗎?

大部分時候我們並沒有在系統中使用多線程,所以很少有人會關注這個問題。單例 bean 存在線程問題,主要是因爲當多個線程操作同一個對象的時候,對這個對象的非靜態成員變量的寫操作會存在線程安全問題。

常見的有兩種解決辦法:

  1. 在Bean對象中儘量避免定義可變的成員變量(不太現實)。

  2. 在類中定義一個ThreadLocal成員變量,將需要的可變成員變量保存在 ThreadLocal 中(推薦的一種方式)。

(5)SpringMVC 工作原理了解嗎?

 

流程說明(重要):

  1. 客戶端(瀏覽器)發送請求,直接請求到 DispatcherServlet
  2. DispatcherServlet 根據請求信息調用 HandlerMapping,解析請求對應的 Handler
  3. 解析到對應的 Handler(也就是我們平常說的 Controller 控制器)後,開始由 HandlerAdapter 適配器處理。
  4. HandlerAdapter 會根據 Handler來調用真正的處理器開處理請求,並處理相應的業務邏輯。
  5. 處理器處理完業務後,會返回一個 ModelAndView 對象,Model 是返回的數據對象,View 是個邏輯上的 View
  6. ViewResolver 會根據邏輯 View 查找實際的 View
  7. DispaterServlet 把返回的 Model 傳給 View(視圖渲染)。
  8. 把 View 返回給請求者(瀏覽器)

(6)Spring 框架中用到了哪些設計模式?

關於下面一些設計模式的詳細介紹,可以看筆主前段時間的原創文章《面試官:“談談Spring中都用到了那些設計模式?”。》 。

  • 工廠設計模式 : Spring使用工廠模式通過 BeanFactoryApplicationContext 創建 bean 對象。
  • 代理設計模式 : Spring AOP 功能的實現。
  • 單例設計模式 : Spring 中的 Bean 默認都是單例的。
  • 模板方法模式 : Spring 中 jdbcTemplatehibernateTemplate 等以 Template 結尾的對數據庫操作的類,它們就使用到了模板模式。
  • 包裝器設計模式 : 我們的項目需要連接多個數據庫,而且不同的客戶在每次訪問中根據需要會去訪問不同的數據庫。這種模式讓我們可以根據客戶的需求能夠動態切換不同的數據源。
  • 觀察者模式: Spring 事件驅動模型就是觀察者模式很經典的一個應用。
  • 適配器模式 :Spring AOP 的增強或通知(Advice)使用到了適配器模式、spring MVC 中也是用到了適配器模式適配Controller

(7)@Component 和 @Bean 的區別是什麼?

  1. 用對象不同: @Component 註解作用於類,而@Bean註解作用於方法。
  2. @Component通常是通過類路徑掃描來自動偵測以及自動裝配到Spring容器中(我們可以使用 @ComponentScan 註解定義要掃描的路徑從中找出標識了需要裝配的類自動裝配到 Spring 的 bean 容器中)。@Bean 註解通常是我們在標有該註解的方法中定義產生這個 bean,@Bean告訴了Spring這是某個類的示例,當我需要用它的時候還給我。
  3. @Bean 註解比 Component 註解的自定義性更強,而且很多地方我們只能通過 @Bean 註解來註冊bean。比如當我們引用第三方庫中的類需要裝配到 Spring容器時,則只能通過 @Bean來實現。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章