1. 程式人生 > 其它 >Spring面試題(2022最新版)

Spring面試題(2022最新版)

Spring面試題(2022最新版)

什麼是spring?
Spring是一個輕量級Java開發框架,最早有Rod Johnson建立,目的是為了解決企業級應用開發的業務邏輯層和其他各層的耦合問題。它是一個分層的JavaSE/JavaEE full-stack(一站式)輕量級開源框架,為開發Java應用程式提供全面的基礎架構支援。Spring負責基礎架構,因此Java開發者可以專注於應用程式的開發。
 依賴於它的兩個核心特性,也就是依賴注入(dependency injection,DI)和麵向切面程式設計(aspect-oriented programming,AOP)。
Spring的優缺點是什麼?
優點

方便解耦,簡化開發

Spring就是一個大工廠,可以將所有物件的建立和依賴關係的維護,交給Spring管理。

AOP程式設計的支援

Spring提供面向切面程式設計,可以方便的實現對程式進行許可權攔截、執行監控等功能。

宣告式事務的支援

只需要通過配置就可以完成對事務的管理,而無需手動程式設計。

方便程式的測試

Spring對Junit4支援,可以通過註解方便的測試Spring程式。

方便整合各種優秀框架

Spring不排斥各種優秀的開源框架,其內部提供了對各種優秀框架的直接支援(如:Struts、Hibernate、MyBatis等)。

降低JavaEE API的使用難度

Spring對JavaEE開發中非常難用的一些API(JDBC、JavaMail、遠端呼叫等),都提供了封裝,使這些API應用難度大大降低。

缺點

Spring明明一個很輕量級的框架,卻給人感覺大而全
Spring依賴反射,反射影響效能
使用門檻升高,入門Spring需要較長時間
 

Spring由哪些模組組成?

Spring 總共大約有 20 個模組, 由 1300 多個不同的檔案構成。 而這些元件被分別整合在核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和裝置支援(Instrmentation) 、資料訪問與整合(Data Access/Integeration) 、 Web、 訊息(Messaging) 、 Test
spring core:提供了框架的基本組成部分,包括控制反轉(Inversion of Control,IOC)和依賴注入(Dependency Injection,DI)功能。
spring beans:提供了BeanFactory,是工廠模式的一個經典實現,Spring將管理物件稱為Bean。
spring context:構建於 core 封裝包基礎上的 context 封裝包,提供了一種框架式的物件訪問方法。
spring jdbc:提供了一個JDBC的抽象層,消除了煩瑣的JDBC編碼和資料庫廠商特有的錯誤程式碼解析, 用於簡化JDBC。
spring aop:提供了面向切面的程式設計實現,讓你可以自定義攔截器、切點等。
spring Web:提供了針對 Web 開發的整合特性,例如檔案上傳,利用 servlet listeners 進行 ioc 容器初始化和針對 Web 的 ApplicationContext。
spring test:主要為測試提供支援的,支援使用JUnit或TestNG對Spring元件進行單元測試和整合測試。
 

Spring 框架中都用到了哪些設計模式?

工廠模式:BeanFactory就是簡單工廠模式的體現,用來建立物件的例項;
單例模式:Bean預設為單例模式。
代理模式:Spring的AOP功能用到了JDK的動態代理和CGLIB位元組碼生成技術;
模板方法:用來解決程式碼重複的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。
觀察者模式:定義物件鍵一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都會得到通知被制動更新,如Spring中listener的實現–ApplicationListener。

詳細講解一下核心容器(spring context應用上下文) 模組

這是基本的Spring模組,提供spring 框架的基礎功能,BeanFactory 是 任何以spring為基礎的應用的核心。Spring 框架建立在此模組之上,它使Spring成為一個容器。
Bean 工廠是工廠模式的一個實現,提供了控制反轉功能,用來把應用的配置和依賴從真正的應用程式碼中分離。最常用的就是org.springframework.beans.factory.xml.XmlBeanFactory ,它根據XML檔案中的定義載入beans。該容器從XML 檔案讀取配置元資料並用它去建立一個完全配置的系統或應用。

Spring框架中有哪些不同型別的事件

Spring 提供了以下5種標準的事件:

上下文更新事件(ContextRefreshedEvent):在呼叫ConfigurableApplicationContext 介面中的refresh()方法時被觸發。

上下文開始事件(ContextStartedEvent):當容器呼叫ConfigurableApplicationContext的Start()方法開始/重新開始容器時觸發該事件。

上下文停止事件(ContextStoppedEvent):當容器呼叫ConfigurableApplicationContext的Stop()方法停止容器時觸發該事件。

上下文關閉事件(ContextClosedEvent):當ApplicationContext被關閉時觸發該事件。容器被關閉時,其管理的所有單例Bean都被銷燬。

請求處理事件(RequestHandledEvent):在Web應用中,當一個http請求(request)結束觸發該事件。如果一個bean實現了ApplicationListener介面,當一個ApplicationEvent 被髮布以後,bean會自動被通知。
 

控制反轉(IoC)有什麼作用

解耦,由spring容器去維護具體的物件
託管了類的產生過程,比如我們需要在類的產生過程中做一些處理,最直接的例子就是代理,如果有容器程式可以把這部分處理交給容器,應用程式則無需去關心類是如何完成代理的

BeanFactory 和 ApplicationContext有什麼區別?

BeanFactory和ApplicationContext是Spring的兩大核心介面,都可以當做Spring的容器。其中ApplicationContext是BeanFactory的子介面。
BeanFactory:是Spring裡面最底層的介面,包含了各種Bean的定義,讀取bean配置文件,管理bean的載入、例項化,控制bean的生命週期,維護bean之間的依賴關係。
ApplicationContext介面作為BeanFactory的派生,除了提供BeanFactory所具有的功能外,還提供了更完整的框架功能:

ApplicationContext通常的實現是什麼?

FileSystemXmlApplicationContext :此容器從一個XML檔案中載入beans的定義,XML Bean 配置檔案的全路徑名必須提供給它的建構函式。
ClassPathXmlApplicationContext:此容器也從一個XML檔案中載入beans的定義,這裡,你需要正確設定classpath因為這個容器將在classpath裡找bean配置。
WebXmlApplicationContext:此容器載入一個XML檔案,此檔案定義了一個WEB應用的所有bean。

什麼是Spring的依賴注入?

控制反轉IoC是一個很大的概念,可以用不同的方式來實現。其主要實現方式有兩種:依賴注入和依賴查詢
依賴注入:相對於IoC而言,依賴注入(DI)更加準確地描述了IoC的設計理念。所謂依賴注入(Dependency Injection),即元件之間的依賴關係由容器在應用系統執行期來決定,也就是由容器動態地將某種依賴關係的目標物件例項注入到應用系統中的各個關聯的元件之中。元件不做定位查詢,只提供普通的Java方法讓容器去決定依賴關係。

有哪些不同型別的依賴注入實現方式?

介面注入(Interface Injection),Setter方法注入(Setter Injection)和構造器注入(Constructor Injection)三種方式。其中介面注入由於在靈活性和易用性比較差,現在從Spring4開始已被廢棄。

構造器依賴注入:構造器依賴注入通過容器觸發一個類的構造器來實現的,該類有一系列引數,每個引數代表一個對其他類的依賴。

Setter方法注入:Setter方法注入是容器通過呼叫無參構造器或無參static工廠 方法例項化bean之後,呼叫該bean的setter方法,即實現了基於setter的依賴注入

解釋Spring支援的幾種bean的作用域

Spring框架支援以下五種bean的作用域:
singleton : bean在每個Spring ioc 容器中只有一個例項。
prototype:一個bean的定義可以有多個例項。
request:每次http請求都會建立一個bean,該作用域僅在基於web的Spring ApplicationContext情形下有效。
session:在一個HTTP Session中,一個bean定義對應一個例項。該作用域僅在基於web的Spring ApplicationContext情形下有效。
global-session:在一個全域性的HTTP Session中,一個bean定義對應一個例項。該作用域僅在基於web的Spring ApplicationContext情形下有效。

Spring框架中的單例bean是執行緒安全的嗎?

不是,Spring框架中的單例bean不是執行緒安全的。
spring 中的 bean 預設是單例模式,spring 框架並沒有對單例 bean 進行多執行緒的封裝處理。
實際上大部分時候 spring bean 無狀態的(比如 dao 類),所有某種程度上來說 bean 也是安全的,但如果 bean 有狀態的話(比如 view model 物件),那就要開發者自己去保證執行緒安全了,最簡單的就是改變 bean 的作用域,把“singleton”變更為“prototype”,這樣請求 bean 相當於 new Bean()了,所以就可以保證執行緒安全了。
有狀態就是有資料儲存功能。
無狀態就是不會儲存資料。
Spring如何處理執行緒併發問題?
在一般情況下,只有無狀態的Bean才可以在多執行緒環境下共享,在Spring中,絕大部分Bean都可以宣告為singleton作用域,因為Spring對一些Bean中非執行緒安全狀態採用ThreadLocal進行處理,解決執行緒安全問題。

ThreadLocal和執行緒同步機制都是為了解決多執行緒中相同變數的訪問衝突問題。同步機制採用了“時間換空間”的方式,僅提供一份變數,不同的執行緒在訪問前需要獲取鎖,沒獲得鎖的執行緒則需要排隊。而ThreadLocal採用了“空間換時間”的方式。

ThreadLocal會為每一個執行緒提供一個獨立的變數副本,從而隔離了多個執行緒對資料的訪問衝突。因為每一個執行緒都擁有自己的變數副本,從而也就沒有必要對該變數進行同步了。ThreadLocal提供了執行緒安全的共享物件,在編寫多執行緒程式碼時,可以把不安全的變數封裝進ThreadLocal。

 

解釋Spring框架中bean的生命週期

在傳統的Java應用中,bean的生命週期很簡單。使用Java關鍵字new進行bean例項化,然後該bean就可以使用了。一旦該bean不再被使用,則由Java自動進行垃圾回收。相比之下,Spring容器中的bean的生命週期就顯得相對複雜多了。正確理解Spring bean的生命週期非常重要,因為你或許要利用Spring提供的擴充套件點來自定義bean的建立過程。 
bean在Spring容器中從建立到銷燬經歷了若干階段,每一階段都可以針對Spring如何管理bean進行個性化定製。
Spring對bean進行例項化;

Spring將值和bean的引用注入到bean對應的屬性中;

如果bean實現了BeanNameAware介面,Spring將bean的ID傳遞給setBean-Name()方法;

如果bean實現了BeanFactoryAware介面,Spring將呼叫setBeanFactory()方法,將BeanFactory容器例項傳入;

如果bean實現了ApplicationContextAware介面,Spring將呼叫setApplicationContext()方法,將bean所在的應用上下文的引用傳入進來;

如果bean實現了BeanPostProcessor介面,Spring將呼叫它們的post-ProcessBeforeInitialization()方法;

如果bean實現了InitializingBean介面,Spring將呼叫它們的after-PropertiesSet()方法。類似地,如果bean使用initmethod聲明瞭初始化方法,該方法也會被呼叫;

如果bean實現了BeanPostProcessor介面,Spring將呼叫它們的post-ProcessAfterInitialization()方法;

此時,bean已經準備就緒,可以被應用程式使用了,它們將一直駐留在應用上下文中,直到該應用上下文被銷燬;

如果bean實現了DisposableBean介面,Spring將呼叫它的destroy()介面方法。同樣,如果bean使用destroy-method聲明瞭銷燬方法,該方法也會被呼叫。

現在你已經瞭解瞭如何建立和載入一個Spring容器。但是一個空的容器並沒有太大的價值,在你把東西放進去之前,它裡面什麼都沒有。為了從Spring的DI(依賴注入)中受益,我們必須將應用物件裝配進Spring容器中。
 

哪些是重要的bean生命週期方法? 你能過載它們嗎?

有兩個重要的bean 生命週期方法,第一個是setup , 它是在容器載入bean的時候被呼叫。第二個方法是 teardown 它是在容器解除安裝類的時候被呼叫。
bean 標籤有兩個重要的屬性(init-method和destroy-method)。用它們你可以自己定製初始化和登出方法。它們也有相應的註解(@PostConstruct和@PreDestroy)

使用@Autowired註解自動裝配的過程是怎樣的?

使用@Autowired註解來自動裝配指定的bean。在使用@Autowired註解之前需要在Spring配置檔案進行配置,<context:annotation-config />。

在啟動spring IoC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor後置處理器,當容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查詢需要的bean,並裝配給該物件的屬性。在使用@Autowired時,首先在容器中查詢對應型別的bean:
如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的資料;
如果查詢的結果不止一個,那麼@Autowired會根據名稱來查詢;
如果上述查詢的結果為空,那麼會丟擲異常。解決方法時,使用required=false。

@Required 註解有什麼作用

這個註解表明bean的屬性必須在配置的時候設定,通過一個bean定義的顯式的屬性值或通過自動裝配,若@Required註解的bean屬性未被設定,容器將丟擲BeanInitializationException。

@Autowired 註解有什麼作用

@Autowired預設是按照型別裝配注入的,預設情況下它要求依賴物件必須存在(可以設定它required屬性為false)。@Autowired 註解提供了更細粒度的控制,包括在何處以及如何完成自動裝配。它的用法和@Required一樣,修飾setter方法、構造器、屬性或者具有任意名稱和/或多個引數的PN方法。
 

@Autowired和@Resource之間的區別

 @Autowired可用於:建構函式、成員變數、Setter方法
@Autowired預設是按照型別裝配注入的,預設情況下它要求依賴物件必須存在(可以設定它required屬性為false)。
@Resource預設是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean才會按照型別來裝配注入。
 

@Qualifier 註解有什麼作用

當您建立多個相同型別的 bean 並希望僅使用屬性裝配其中一個 bean 時,您可以使用@Qualifier 註解和 @Autowired 通過指定應該裝配哪個確切的 bean 來消除歧義。

@RequestMapping 註解有什麼用?

@RequestMapping 註解用於將特定 HTTP 請求方法對映到將處理相應請求的控制器中的特定類/方法。此註釋可應用於兩個級別:
類級別:對映請求的 URL
方法級別:對映 URL 以及 HTTP 請求方法

說一下Spring的事務傳播行為

spring事務的傳播行為說的是,當多個事務同時存在的時候,spring如何處理這些事務的行為。
① PROPAGATION_REQUIRED:如果當前沒有事務,就建立一個新事務,如果當前存在事務,就加入該事務,該設定是最常用的設定。
② PROPAGATION_SUPPORTS:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行。
③ PROPAGATION_MANDATORY:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就丟擲異常。

④ PROPAGATION_REQUIRES_NEW:建立新事務,無論當前存不存在事務,都建立新事務。

⑤ PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

⑥ PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則丟擲異常。

⑦ PROPAGATION_NESTED:如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則按REQUIRED屬性執行。
 

說一下 spring 的事務隔離?

spring 有五大隔離級別,預設值為 ISOLATION_DEFAULT(使用資料庫的設定),其他四個隔離級別和資料庫的隔離級別一致:

ISOLATION_DEFAULT:用底層資料庫的設定隔離級別,資料庫設定的是什麼我就用什麼;

ISOLATION_READ_UNCOMMITTED:未提交讀,最低隔離級別、事務未提交前,就可被其他事務讀取(會出現幻讀、髒讀、不可重複讀);

ISOLATION_READ_COMMITTED:提交讀,一個事務提交後才能被其他事務讀取到(會造成幻讀、不可重複讀),SQL server 的預設級別;

ISOLATION_REPEATABLE_READ:可重複讀,保證多次讀取同一個資料時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的資料(會造成幻讀),MySQL 的預設級別;

ISOLATION_SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止髒讀、不可重複讀、幻讀。

髒讀 :表示一個事務能夠讀取另一個事務中還未提交的資料。比如,某個事務嘗試插入記錄 A,此時該事務還未提交,然後另一個事務嘗試讀取到了記錄 A。

不可重複讀 :是指在一個事務內,多次讀同一資料。

幻讀 :指同一個事務內多次查詢返回的結果集不一樣。比如同一個事務 A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄,這就好像產生了幻覺。發生幻讀的原因也是另外一個事務新增或者刪除或者修改了第一個事務結果集裡面的資料,同一個記錄的資料內容被修改了,所有資料行的記錄就變多或者變少了。
 

什麼是AOP

OOP(Object-Oriented Programming)面向物件程式設計,允許開發者定義縱向的關係,但並適用於定義橫向的關係,導致了大量程式碼的重複,而不利於各個模組的重用。

AOP(Aspect-Oriented Programming),一般稱為面向切面程式設計,作為面向物件的一種補充,用於將那些與業務無關,但卻對多個物件產生影響的公共行為和邏輯,抽取並封裝為一個可重用的模組,這個模組被命名為“切面”(Aspect),減少系統中的重複程式碼,降低了模組間的耦合度,同時提高了系統的可維護性。可用於許可權認證、日誌、事務處理等。
 
JDK動態代理和CGLIB動態代理的區別
Spring AOP中的動態代理主要有兩種方式,JDK動態代理和CGLIB動態代理:

JDK動態代理只提供介面的代理,不支援類的代理。核心InvocationHandler介面和Proxy類,InvocationHandler 通過invoke()方法反射來呼叫目標類中的程式碼,動態地將橫切邏輯和業務編織在一起;接著,Proxy利用 InvocationHandler動態建立一個符合某一介面的的例項, 生成目標類的代理物件。

如果代理類沒有實現 InvocationHandler 介面,那麼Spring AOP會選擇使用CGLIB來動態代理目標類。CGLIB(Code Generation Library),是一個程式碼生成的類庫,可以在執行時動態的生成指定類的一個子類物件,並覆蓋其中特定方法並新增增強程式碼,從而實現AOP。CGLIB是通過繼承的方式做的動態代理,因此如果某個類被標記為final,那麼它是無法使用CGLIB做動態代理的。
 

解釋一下Spring AOP裡面的幾個名詞

(1)切面(Aspect):切面是通知和切點的結合。通知和切點共同定義了切面的全部內容。 在Spring AOP中,切面可以使用通用類(基於模式的風格) 或者在普通類中以 @AspectJ 註解來實現。

(2)連線點(Join point):指方法,在Spring AOP中,一個連線點 總是 代表一個方法的執行。 應用可能有數以千計的時機應用通知。這些時機被稱為連線點。連線點是在應用執行過程中能夠插入切面的一個點。這個點可以是呼叫方法時、丟擲異常時、甚至修改一個欄位時。切面程式碼可以利用這些點插入到應用的正常流程之中,並新增新的行為。

(3)通知(Advice):在AOP術語中,切面的工作被稱為通知。

(4)切入點(Pointcut):切點的定義會匹配通知所要織入的一個或多個連線點。我們通常使用明確的類和方法名稱,或是利用正則表示式定義所匹配的類和方法名稱來指定這些切點。

(5)引入(Introduction):引入允許我們向現有類新增新方法或屬性。

(6)目標物件(Target Object): 被一個或者多個切面(aspect)所通知(advise)的物件。它通常是一個代理物件。也有人把它叫做 被通知(adviced) 物件。 既然Spring AOP是通過執行時代理實現的,這個物件永遠是一個 被代理(proxied) 物件。

(7)織入(Weaving):織入是把切面應用到目標物件並建立新的代理物件的過程。在目標物件的生命週期裡有多少個點可以進行織入:

編譯期:切面在目標類編譯時被織入。AspectJ的織入編譯器是以這種方式織入切面的。
類載入期:切面在目標類載入到JVM時被織入。需要特殊的類載入器,它可以在目標類被引入應用之前增強該目標類的位元組碼。AspectJ5的載入時織入就支援以這種方式織入切面。
執行期:切面在應用執行的某個時刻被織入。一般情況下,在織入切面時,AOP容器會為目標物件動態地建立一個代理物件。SpringAOP就是以這種方式織入切面。
 

Spring通知有哪些型別?

在AOP術語中,切面的工作被稱為通知,實際上是程式執行時要通過SpringAOP框架觸發的程式碼段。
Spring切面可以應用5種類型的通知:
前置通知(Before):在目標方法被呼叫之前呼叫通知功能;
後置通知(After):在目標方法完成之後呼叫通知,此時不會關心方法的輸出是什麼;
返回通知(After-returning ):在目標方法成功執行之後呼叫通知;
異常通知(After-throwing):在目標方法丟擲異常後呼叫通知;
環繞通知(Around):通知包裹了被通知的方法,在被通知的方法呼叫之前和呼叫之後執行自定義的行為。