那年,這個Spring大家族讓我在面試中脫穎而出

退役的bug程式設計師發表於2020-10-26

前言:

Spring框架就像一個家族,有眾多衍生產品例如boot、security、jpa等等。但他們的基礎都是Spring的ioc和aop。ioc提供了依賴注入的容器,aop解決了面向橫切面的程式設計;然後在此二者的基礎上實現了其他延伸產品的高階功能。今天就仔細聊一聊Spring的大家族的故事。
在這裡插入圖片描述

在這裡插入圖片描述

1. 為什麼要使用 spring?

spring 提供 ioc 技術,容器會幫你管理依賴的物件,從而不需要自己建立和管理依賴物件了,更輕鬆的實現了程式的解耦。
spring 提供了事務支援,使得事務操作變的更加方便。
spring 提供了面向切片程式設計,這樣可以更方便的處理某一類的問題。
更方便的框架整合,spring 可以很方便的整合其他框架,比如 MyBatis、hibernate 等。

2. 解釋一下什麼是 aop?

aop 是面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。
簡單來說就是統一處理某一“切面”(類)的問題的程式設計思想,比如統一處理日誌、異常等。

另外本人整理收藏了20年多家公司面試知識點整理 ,以及各種Java核心知識點免費分享給大家,我認為對面試來說是非常有用的,想要資料的話請點795983544 暗號CSDN。

在這裡插入圖片描述

3. 解釋一下什麼是 ioc?

ioc:Inversionof Control(中文:控制反轉)是 spring 的核心,對於 spring 框架來說,就是由 spring 來負責控制物件的生命週期和物件間的關係。
簡單來說,控制指的是當前物件對內部成員的控制權;控制反轉指的是,這種控制權不由當前物件管理了,由其他(類,第三方容器)來管理。

4. spring 有哪些主要模組?

spring core:框架的最基礎部分,提供 ioc 和依賴注入特性。
spring context:構建於 core 封裝包基礎上的 context 封裝包,提供了一種框架式的物件訪問方法。
spring dao:Data Access Object 提供了JDBC的抽象層。
spring aop:提供了面向切面的程式設計實現,讓你可以自定義攔截器、切點等。
spring Web:提供了針對 Web 開發的整合特性,例如檔案上傳,利用 servlet listeners 進行 ioc 容器初始化和針對 Web 的 ApplicationContext。
spring Web mvc:spring 中的 mvc 封裝包提供了 Web 應用的 Model-View-Controller(MVC)的實現。

5. spring 常用的注入方式有哪些?

setter 屬性注入
構造方法注入
註解方式注入

6. spring 中的 bean 是執行緒安全的嗎?

spring 中的 bean 預設是單例模式,spring 框架並沒有對單例 bean 進行多執行緒的封裝處理。
實際上大部分時候 spring bean 無狀態的(比如 dao 類),所有某種程度上來說 bean 也是安全的,但如果 bean 有狀態的話(比如 view model 物件),那就要開發者自己去保證執行緒安全了,最簡單的就是改變 bean 的作用域,把“singleton”變更為“prototype”,這樣請求 bean 相當於 new Bean()了,所以就可以保證執行緒安全了。
有狀態就是有資料儲存功能。
無狀態就是不會儲存資料。

7. spring 支援幾種 bean 的作用域?

spring 支援 5 種作用域,如下:
singleton:spring ioc 容器中只存在一個 bean 例項,bean 以單例模式存在,是系統預設值;
prototype:每次從容器呼叫 bean 時都會建立一個新的示例,既每次 getBean()相當於執行 new Bean()操作;
Web 環境下的作用域:
request:每次 http 請求都會建立一個 bean;
session:同一個 http session 共享一個 bean 例項;
global-session:用於 portlet 容器,因為每個 portlet 有單獨的 session,globalsession 提供一個全域性性的 http session。
注意: 使用 prototype 作用域需要慎重的思考,因為頻繁建立和銷燬 bean 會帶來很大的效能開銷。

8. spring 自動裝配 bean 有哪些方式?

no:預設值,表示沒有自動裝配,應使用顯式 bean 引用進行裝配。
byName:它根據 bean 的名稱注入物件依賴項。
byType:它根據型別注入物件依賴項。
建構函式:通過建構函式來注入依賴項,需要設定大量的引數。
autodetect:容器首先通過建構函式使用 autowire 裝配,如果不能,則通過 byType 自動裝配。

9. spring 事務實現方式有哪些?

宣告式事務:宣告式事務也有兩種實現方式,基於 xml 配置檔案的方式和註解方式(在類上新增 @Transaction 註解)。
編碼方式:提供編碼的形式管理和維護事務。

10. 說一下 spring 的事務隔離?

在這裡插入圖片描述

spring 有五大隔離級別,預設值為 ISOLATION_DEFAULT(使用資料庫的設定),其他四個隔離級別和資料庫的隔離級別一致:
ISOLATION_DEFAULT:用底層資料庫的設定隔離級別,資料庫設定的是什麼我就用什麼;
ISOLATIONREADUNCOMMITTED:未提交讀,最低隔離級別、事務未提交前,就可被其他事務讀取(會出現幻讀、髒讀、不可重複讀);
ISOLATIONREADCOMMITTED:提交讀,一個事務提交後才能被其他事務讀取到(會造成幻讀、不可重複讀),SQL server 的預設級別;
ISOLATIONREPEATABLEREAD:可重複讀,保證多次讀取同一個資料時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的資料(會造成幻讀),MySQL 的預設級別;
ISOLATION_SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止髒讀、不可重複讀、幻讀。
髒讀 :表示一個事務能夠讀取另一個事務中還未提交的資料。比如,某個事務嘗試插入記錄 A,此時該事務還未提交,然後另一個事務嘗試讀取到了記錄 A。
不可重複讀 :是指在一個事務內,多次讀同一資料。
幻讀 :指同一個事務內多次查詢返回的結果集不一樣。比如同一個事務 A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄,這就好像產生了幻覺。發生幻讀的原因也是另外一個事務新增或者刪除或者修改了第一個事務結果集裡面的資料,同一個記錄的資料內容被修改了,所有資料行的記錄就變多或者變少了。

11. 說一下 spring mvc 執行流程?

spring mvc 先將請求傳送給 DispatcherServlet。
DispatcherServlet 查詢一個或多個 HandlerMapping,找到處理請求的 Controller。
DispatcherServlet 再把請求提交到對應的 Controller。
Controller 進行業務邏輯處理後,會返回一個ModelAndView。
Dispathcher 查詢一個或多個 ViewResolver 檢視解析器,找到 ModelAndView 物件指定的檢視物件。
檢視物件負責渲染返回給客戶端。

12. spring mvc 有哪些元件?

前置控制器 DispatcherServlet。
對映控制器 HandlerMapping。
處理器 Controller。
模型和檢視 ModelAndView。
檢視解析器 ViewResolver。

13. @RequestMapping 的作用是什麼?

將 http 請求對映到相應的類/方法上。

14. @Autowired 的作用是什麼?

@Autowired 它可以對類成員變數、方法及建構函式進行標註,完成自動裝配的工作,通過@Autowired 的使用來消除 set/get 方法。
Spring Boot/Spring Cloud

15. 什麼是 spring boot?

spring boot 是為 spring 服務的,是用來簡化新 spring 應用的初始搭建以及開發過程的。

16. 為什麼要用 spring boot?

配置簡單
獨立執行
自動裝配
無程式碼生成和 xml 配置
提供應用監控
易上手
提升開發效率

17. spring boot 核心配置檔案是什麼?

spring boot 核心的兩個配置檔案:
bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 載入的,比 applicaton 優先載入,且 boostrap 裡面的屬性不能被覆蓋;
application (. yml 或者 . properties):用於 spring boot 專案的自動化配置。

18. spring boot 配置檔案有哪幾種型別?它們有什麼區別?

配置檔案有 . properties 格式和 . yml 格式,它們主要的區別是書法風格不同。
. properties 配置如下:
spring. RabbitMQ. port=5672
. yml 配置如下:
spring:
RabbitMQ:
port: 5672
. yml 格式不支援 @PropertySource 註解匯入。

19. spring boot 有哪些方式可以實現熱部署?

使用 devtools 啟動熱部署,新增 devtools 庫,在配置檔案中把 spring. devtools. restart. enabled 設定為 true;
使用 Intellij Idea 編輯器,溝上自動編譯或手動重新編譯。

20. 什麼是 spring cloud?

spring cloud 是一系列框架的有序集合。它利用 spring boot 的開發便利性巧妙地簡化了分散式系統基礎設施的開發,如服務發現註冊、配置中心、訊息匯流排、負載均衡、斷路器、資料監控等,都可以用 spring boot 的開發風格做到一鍵啟動和部署。

21. spring cloud 斷路器的作用是什麼?

在分散式架構中,斷路器模式的作用也是類似的,當某個服務單元發生故障(類似用電器發生短路)之後,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得執行緒因呼叫故障服務被長時間佔用不釋放,避免了故障在分散式系統中的蔓延。

22. spring cloud 的核心元件有哪些?

Eureka:服務註冊於發現。
Feign:基於動態代理機制,根據註解和選擇的機器,拼接請求 url 地址,發起請求。
Ribbon:實現負載均衡,從一個服務的多臺機器中選擇一臺。
Hystrix:提供執行緒池,不同的服務走不同的執行緒池,實現了不同服務呼叫的隔離,避免了服務雪崩的問題。
Zuul:閘道器管理,由 Zuul 閘道器轉發請求給對應的服務。
Hibernate

23. 為什麼要使用 hibernate?

hibernate 是對 jdbc 的封裝,大大簡化了資料訪問層的繁瑣的重複性程式碼。
hibernate 是一個優秀的 ORM 實現,很多程度上簡化了 DAO 層的編碼功能。
可以很方便的進行資料庫的移植工作。
提供了快取機制,是程式執行更改的高效。

24. 什麼是 ORM 框架?

ORM(Object Relation Mapping)物件關係對映,是把資料庫中的關係資料對映成為程式中的物件。
使用 ORM 的優點:提高了開發效率降低了開發成本、開發更簡單更物件化、可移植更強。

25. hibernate 中如何在控制檯檢視列印的 SQL 語句?

在 Config 裡面把 hibernate. show_SQL 設定為 true 就可以。但不建議開啟,開啟之後會降低程式的執行效率。

26. hibernate 有幾種查詢方式?

三種:hql、原生 SQL、條件查詢 Criteria。

27. hibernate 實體類可以被定義為 final 嗎?

實體類可以定義為 final 類,但這樣的話就不能使用 hibernate 代理模式下的延遲關聯提供效能了,所以不建議定義實體類為 final。

28. 在 hibernate 中使用 Integer 和 int 做對映有什麼區別?

Integer 型別為物件,它的值允許為 null,而 int 屬於基礎資料型別,值不能為 null。

29. hibernate 是如何工作的?

讀取並解析配置檔案。
讀取並解析對映檔案,建立 SessionFactory。
開啟 Session。
建立事務。
進行持久化操作。
提交事務。
關閉 Session。
關閉 SessionFactory。

30. get()和 load()的區別?

資料查詢時,沒有 OID 指定的物件,get() 返回 null;load() 返回一個代理物件。
load()支援延遲載入;get() 不支援延遲載入。

31. 說一下 hibernate 的快取機制?

hibernate 常用的快取有一級快取和二級快取:
一級快取:也叫 Session 快取,只在 Session 作用範圍內有效,不需要使用者干涉,由 hibernate 自身維護,可以通過:evict(object)清除 object 的快取;clear()清除一級快取中的所有快取;flush()刷出快取;
二級快取:應用級別的快取,在所有 Session 中都有效,支援配置第三方的快取,如:EhCache。

32. hibernate 物件有哪些狀態?

臨時/瞬時狀態:直接 new 出來的物件,該物件還沒被持久化(沒儲存在資料庫中),不受 Session 管理。
持久化狀態:當呼叫 Session 的 save/saveOrupdate/get/load/list 等方法的時候,物件就是持久化狀態。
遊離狀態:Session 關閉之後物件就是遊離狀態。

33. 在 hibernate 中 getCurrentSession 和 openSession 的區別是什麼?

getCurrentSession 會繫結當前執行緒,而 openSession 則不會。
getCurrentSession 事務是 Spring 控制的,並且不需要手動關閉,而 openSession 需要我們自己手動開啟和提交事務。

34. hibernate 實體類必須要有無參建構函式嗎?為什麼?

hibernate 中每個實體類必須提供一個無參建構函式,因為 hibernate 框架要使用 reflection api,通過呼叫 ClassnewInstance() 來建立實體類的例項,如果沒有無參的建構函式就會丟擲異常。
MyBatis

35. MyBatis 中 #{}和 的區別是什麼?#是預編譯處理,{}的區別是什麼?#{}是預編譯處理,的區別是什麼?

這個#是預編譯處理,{}是字元替換。 在使用 #{}時,MyBatis 會將 SQL 中的 #{}替換成“?”,配合 PreparedStatement 的 set 方法賦值,這樣可以有效的防止 SQL 注入,保證程式的執行安全。

36. MyBatis 有幾種分頁方式?

分頁方式:邏輯分頁和物理分頁。
邏輯分頁: 使用 MyBatis 自帶的 RowBounds 進行分頁,它是一次性查詢很多資料,然後在資料中再進行檢索。
物理分頁: 自己手寫 SQL 分頁或使用分頁外掛 PageHelper,去資料庫查詢指定條數的分頁資料的形式。

37. RowBounds 是一次性查詢全部結果嗎?為什麼?

RowBounds 表面是在“所有”資料中檢索資料,其實並非是一次性查詢出所有資料,因為 MyBatis 是對 jdbc 的封裝,在 jdbc 驅動中有一個 Fetch Size 的配置,它規定了每次最多從資料庫查詢多少條資料,假如你要查詢更的資料,它會在你執行 next()的時候,去查詢更多的資料。就好比你去自動取款機取 10000 元,但取款機每次最多能取 2500 元,所以你要取 4 次才能把錢取完。只是對於 jdbc 來說,當你呼叫 next()的時候會自動幫你完成查詢工作。這樣做的好處可以有效的防止記憶體溢位。
Fetch Size 官方相關文件:http://t. cn/EfSE2g3

38. MyBatis 邏輯分頁和物理分頁的區別是什麼?

邏輯分頁是一次性查詢很多資料,然後再在結果中檢索分頁的資料。這樣做弊端是需要消耗大量的記憶體、有記憶體溢位的風險、對資料庫壓力較大。
物理分頁是從資料庫查詢指定條數的資料,彌補了一次性全部查出的所有資料的種種缺點,比如需要大量的記憶體,對資料庫查詢壓力較大等問題。

39. MyBatis 是否支援延遲載入?延遲載入的原理是什麼?

MyBatis 支援延遲載入,設定 lazyLoadingEnabled=true 即可。
延遲載入的原理的是呼叫的時候觸發載入,而不是在初始化的時候就載入資訊。比如呼叫 a. getB(). getName(),這個時候發現 a. getB() 的值為 null,此時會單獨觸發事先儲存好的關聯 B 物件的 SQL,先查詢出來 B,然後再呼叫 a. setB(b),而這時候再呼叫 a. getB(). getName() 就有值了,這就是延遲載入的基本原理。

40. 說一下 MyBatis 的一級快取和二級快取?

一級快取:基於 PerpetualCache 的 HashMap 本地快取,它的宣告週期是和 SQLSession 一致的,有多個 SQLSession 或者分散式的環境中資料庫操作,可能會出現髒資料。當 Session flush 或 close 之後,該 Session 中的所有 Cache 就將清空,預設一級快取是開啟的。
二級快取:也是基於 PerpetualCache 的 HashMap 本地快取,不同在於其儲存作用域為 Mapper 級別的,如果多個SQLSession之間需要共享快取,則需要使用到二級快取,並且二級快取可自定義儲存源,如 Ehcache。預設不開啟二級快取,要開啟二級快取,使用二級快取屬性類需要實現 Serializable 序列化介面(可用來儲存物件的狀態)。
開啟二級快取資料查詢流程:二級快取 -> 一級快取 -> 資料庫。
快取更新機制:當某一個作用域(一級快取 Session/二級快取 Mapper)進行了C/U/D 操作後,預設該作用域下所有 select 中的快取將被 clear。

41. MyBatis 和 hibernate 的區別有哪些?

靈活性:MyBatis 更加靈活,自己可以寫 SQL 語句,使用起來比較方便。
可移植性:MyBatis 有很多自己寫的 SQL,因為每個資料庫的 SQL 可以不相同,所以可移植性比較差。
學習和使用門檻:MyBatis 入門比較簡單,使用門檻也更低。
二級快取:hibernate 擁有更好的二級快取,它的二級快取可以自行更換為第三方的二級快取。

42. MyBatis 有哪些執行器(Executor)?

MyBatis 有三種基本的Executor執行器:
SimpleExecutor:每執行一次 update 或 select 就開啟一個 Statement 物件,用完立刻關閉 Statement 物件;
ReuseExecutor:執行 update 或 select,以 SQL 作為 key 查詢 Statement 物件,存在就使用,不存在就建立,用完後不關閉 Statement 物件,而是放置於 Map 內供下一次使用。簡言之,就是重複使用 Statement 物件;
BatchExecutor:執行 update(沒有 select,jdbc 批處理不支援 select),將所有 SQL 都新增到批處理中(addBatch()),等待統一執行(executeBatch()),它快取了多個 Statement 物件,每個 Statement 物件都是 addBatch()完畢後,等待逐一執行 executeBatch()批處理,與 jdbc 批處理相同。

43. MyBatis 分頁外掛的實現原理是什麼?

分頁外掛的基本原理是使用 MyBatis 提供的外掛介面,實現自定義外掛,在外掛的攔截方法內攔截待執行的 SQL,然後重寫 SQL,根據 dialect 方言,新增對應的物理分頁語句和物理分頁引數。

44. MyBatis 如何編寫一個自定義外掛?

自定義外掛實現原理
MyBatis 自定義外掛針對 MyBatis 四大物件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)進行攔截:
Executor:攔截內部執行器,它負責呼叫 StatementHandler 運算元據庫,並把結果集通過 ResultSetHandler 進行自動對映,另外它還處理了二級快取的操作;
StatementHandler:攔截 SQL 語法構建的處理,它是 MyBatis 直接和資料庫執行 SQL 指令碼的物件,另外它也實現了 MyBatis 的一級快取;
ParameterHandler:攔截引數的處理;
ResultSetHandler:攔截結果集的處理。
自定義外掛實現關鍵
MyBatis 外掛要實現 Interceptor 介面,介面包含的方法,如下:

public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}

setProperties 方法是在 MyBatis 進行配置外掛的時候可以配置自定義相關屬性,即:介面實現物件的引數配置;
plugin 方法是外掛用於封裝目標物件的,通過該方法我們可以返回目標物件本身,也可以返回一個它的代理,可以決定是否要進行攔截進而決定要返回一個什麼樣的目標物件,官方提供了示例:return Plugin. wrap(target, this);
intercept 方法就是要進行攔截的時候要執行的方法。
自定義外掛實現示例
官方外掛實現:

@Intercepts({@Signature(type = Executor. class, method = “query”,
args = {MappedStatement. class, Object. class, RowBounds. class, ResultHandler. class})})
public class TestInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
Object target = invocation. getTarget(); //被代理物件
Method method = invocation. getMethod(); //代理方法
Object[] args = invocation. getArgs(); //方法引數
// do something . . . . . . 方法攔截前執行程式碼塊
Object result = invocation. proceed();
// do something . . . . . . . 方法攔截後執行程式碼塊
return result;
}
public Object plugin(Object target) {
return Plugin. wrap(target, this);
}
}

45. spring mvc 和 struts 的區別是什麼?

攔截級別:struts2 是類級別的攔截;spring mvc 是方法級別的攔截。
資料獨立性:spring mvc 的方法之間基本上獨立的,獨享 request 和 response 資料,請求資料通過引數獲取,處理結果通過 ModelMap 交回給框架,方法之間不共享變數;而 struts2 雖然方法之間也是獨立的,但其所有 action 變數是共享的,這不會影響程式執行,卻給我們編碼和讀程式時帶來了一定的麻煩。
攔截機制:struts2 有以自己的 interceptor 機制,spring mvc 用的是獨立的 aop 方式,這樣導致struts2 的配置檔案量比 spring mvc 大。
對 ajax 的支援:spring mvc 整合了ajax,所有 ajax 使用很方便,只需要一個註解 @ResponseBody 就可以實現了;而 struts2 一般需要安裝外掛或者自己寫程式碼才行。

五、最後:

針對最近很多人都在面試,我這邊也整理了相當多的面試專題資料,也有其他大廠的面經。希望可以幫助到大家。

下面的面試題答案都整理成文件筆記。也還整理了一些面試資料&最新2020收集的一些大廠的面試真題(都整理成文件,小部分截圖),有需要的可以點選進入暗號CSDN

在這裡插入圖片描述

在這裡插入圖片描述

相關文章