為了即將到來的金九銀十,本文總結了經典的 Spring 面試題,總共 2W 字,建議收藏轉發。
本系列會系統的整理MySQL,Redis,SSM框架,演算法,計網等面試常問技術棧的面試題,本文主要是整理分享了Spring相關的面試題,MySQL之前已經更新了,需要的同學也可以去看一下,希望對正在準備秋招的你們有所幫助!
當然個人整理的所有面試題都無償分享,只求大夥一個點贊關注轉發三連,這些文件都放在文末了,需要的同學可以自取
Spring概述
什麼是spring?
Spring是一個輕量級Java開發框架,最早有Rod Johnson建立,目的是為了解決企業級應用開發的業務邏輯層和其他各層的耦合問題。它是一個分層的JavaSE/JavaEE full-stack(一站式)輕量級開源框架,為開發Java應用程式提供全面的基礎架構支援。Spring負責基礎架構,因此Java開發者可以專注於應用程式的開發。
Spring最根本的使命是解決企業級應用開發的複雜性,即簡化Java開發。
Spring可以做很多事情,它為企業級開發提供給了豐富的功能,但是這些功能的底層都依賴於它的兩個核心特性,也就是依賴注入(dependency injection,DI)和麵向切面程式設計(aspect-oriented programming,AOP)。
為了降低Java開發的複雜性,Spring採取了以下4種關鍵策略
- 基於POJO的輕量級和最小侵入性程式設計;
- 通過依賴注入和麵向介面實現鬆耦合;
- 基於切面和慣例進行宣告式程式設計;
- 通過切面和模板減少樣板式程式碼。
Spring框架的設計目標,設計理念,和核心是什麼
Spring設計目標:Spring為開發者提供一個一站式輕量級應用開發平臺;
Spring設計理念:在JavaEE開發中,支援POJO和JavaBean開發方式,使應用面向介面開發,充分支援OO(物件導向)設計方法;Spring通過IoC容器實現物件耦合關係的管理,並實現依賴反轉,將物件之間的依賴關係交給IoC容器,實現解耦;
Spring框架的核心:IoC容器和AOP模組。通過IoC容器管理POJO物件以及他們之間的耦合關係;通過AOP以動態非侵入的方式增強服務。
IoC讓相互協作的元件保持鬆散的耦合,而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有哪些應用場景
應用場景:JavaEE企業應用開發,包括SSH、SSM等
Spring價值:
- Spring是非侵入式的框架,目標是使應用程式程式碼對框架依賴最小化;
- Spring提供一個一致的程式設計模型,使應用直接使用POJO開發,與執行環境隔離開來;
- Spring推動應用設計風格向物件導向和麵向介面開發轉變,提高了程式碼的重用性和可測試性;
Spring由哪些模組組成?
Spring 總共大約有 20 個模組, 由 1300 多個不同的檔案構成。而這些元件被分別整合在核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和裝置支援(Instrmentation) 、資料訪問與整合(Data Access/Integeration) 、 Web、 訊息(Messaging) 、 Test等 6 個模組中。以下是 Spring 5 的模組結構圖:
- 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會自動被通知。
Spring 應用程式有哪些不同元件?
Spring 應用一般有以下元件:
- 介面 - 定義功能。
- Bean 類 - 它包含屬性,setter 和 getter 方法,函式等。
- Bean 配置檔案 - 包含類的資訊以及如何配置它們。
- Spring 面向切面程式設計(AOP) - 提供面向切面程式設計的功能。
- 使用者程式 - 它使用介面。
使用 Spring 有哪些方式?
使用 Spring 有以下方式:
- 作為一個成熟的 Spring Web 應用程式。
- 作為第三方 Web 框架,使用 Spring Frameworks 中間層。
- 作為企業級 Java Bean,它可以包裝現有的 POJO(Plain Old Java Objects)。
- 用於遠端使用。
Spring控制反轉(IOC)
什麼是Spring IOC 容器?
控制反轉即IoC (Inversion of Control),它把傳統上由程式程式碼直接操控的物件的呼叫權交給容器,通過容器來實現物件元件的裝配和管理。所謂的“控制反轉”概念就是對元件物件控制權的轉移,從程式程式碼本身轉移到了外部容器。
Spring IOC 負責建立物件,管理物件(通過依賴注入(DI),裝配物件,配置物件,並且管理這些物件的整個生命週期。
控制反轉(IoC)有什麼作用
- 管理物件的建立和依賴關係的維護。物件的建立並不是一件簡單的事,在物件關係比較複雜時,如果依賴關係需要程式猿來維護的話,那是相當頭疼的
- 解耦,由容器去維護具體的物件
- 託管了類的產生過程,比如我們需要在類的產生過程中做一些處理,最直接的例子就是代理,如果有容器程式可以把這部分處理交給容器,應用程式則無需去關心類是如何完成代理的
IOC的優點是什麼?
- IOC 或 依賴注入把應用的程式碼量降到最低。
- 它使應用容易測試,單元測試不再需要單例和JNDI查詢機制。
- 最小的代價和最小的侵入性使鬆散耦合得以實現。
- IOC容器支援載入服務時的餓漢式初始化和懶載入。
Spring IoC 的實現機制
Spring 中的 IoC 的實現原理就是工廠模式加反射機制。
示例:
interfaceFruit{
publicabstractvoideat;
}classAppleimplementsFruit{
publicvoideat{
System.out.println("Apple");}}classOrangeimplementsFruit{
publicvoideat{
System.out.println("Orange");}}classFactory{
public static Fruit getInstance(String ClassName) {Fruit f=;try {f=(Fruit)Class.forName(ClassName).newInstance;} catch (Exception e) {e.printStackTrace;}return f;}}classClient{
publicstaticvoidmain(String[] a) {
Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");if(f!=){f.eat;}}}
Spring 的 IoC支援哪些功能
Spring 的 IoC 設計支援以下功能:
- 依賴注入
- 依賴檢查
- 自動裝配
- 支援集合
- 指定初始化方法和銷燬方法
- 支援回撥某些方法(但是需要實現 Spring 介面,略有侵入)
其中,最重要的就是依賴注入,從 XML 的配置上說,即 ref 標籤。對應 Spring RuntimeBeanReference 物件。
對於 IoC 來說,最重要的就是容器。容器管理著 Bean 的生命週期,控制著 Bean 的依賴注入。
BeanFactory 和 ApplicationContext有什麼區別?
BeanFactory和ApplicationContext是Spring的兩大核心介面,都可以當做Spring的容器。其中ApplicationContext是BeanFactory的子介面。
依賴關係
BeanFactory:是Spring裡面最底層的介面,包含了各種Bean的定義,讀取bean配置文件,管理bean的載入、例項化,控制bean的生命週期,維護bean之間的依賴關係。
ApplicationContext介面作為BeanFactory的派生,除了提供BeanFactory所具有的功能外,還提供了更完整的框架功能:
- 繼承MessageSource,因此支援國際化。
- 統一的資原始檔訪問方式。
- 提供在監聽器中註冊bean的事件。
- 同時載入多個配置檔案。
- 載入多個(有繼承關係)上下文 ,使得每一個上下文都專注於一個特定的層次,比如應用的web層。
載入方式
BeanFactroy採用的是延遲載入形式來注入Bean的,即只有在使用到某個Bean時(呼叫getBean),才對該Bean進行載入例項化。這樣,我們就不能發現一些存在的Spring的配置問題。如果Bean的某一個屬性沒有注入,BeanFacotry載入後,直至第一次使用呼叫getBean方法才會丟擲異常。
ApplicationContext,它是在容器啟動時,一次性建立了所有的Bean。這樣,在容器啟動時,我們就可以發現Spring中存在的配置錯誤,這樣有利於檢查所依賴屬性是否注入。ApplicationContext啟動後預載入所有的單例項Bean,通過預載入單例項bean ,確保當你需要的時候,你就不用等待,因為它們已經建立好了。
相對於基本的BeanFactory,ApplicationContext 唯一的不足是佔用記憶體空間。當應用程式配置Bean較多時,程式啟動較慢。
建立方式
BeanFactory通常以程式設計的方式被建立,ApplicationContext還能以宣告的方式建立,如使用ContextLoader。
註冊方式
BeanFactory和ApplicationContext都支援BeanPostProcessor、BeanFactoryPostProcessor的使用,但兩者之間的區別是:BeanFactory需要手動註冊,而ApplicationContext則是自動註冊。
Spring 如何設計容器的,BeanFactory和ApplicationContext的關係詳解
Spring 作者 Rod Johnson 設計了兩個介面用以表示容器。
- BeanFactory
- ApplicationContext
BeanFactory 簡單粗暴,可以理解為就是個 HashMap,Key 是 BeanName,Value 是 Bean 例項。通常只提供註冊(put),獲取(get)這兩個功能。我們可以稱之為 “低階容器”。
ApplicationContext 可以稱之為 “高階容器”。因為他比 BeanFactory 多了更多的功能。他繼承了多個介面。因此具備了更多的功能。例如資源的獲取,支援多種訊息(例如 JSP tag 的支援),對 BeanFactory 多了工具級別的支援等待。所以你看他的名字,已經不是 BeanFactory 之類的工廠了,而是 “應用上下文”, 代表著整個大容器的所有功能。該介面定義了一個 refresh 方法,此方法是所有閱讀 Spring 原始碼的人的最熟悉的方法,用於重新整理整個容器,即重新載入/重新整理所有的 bean。
當然,除了這兩個大介面,還有其他的輔助介面,這裡就不介紹他們了。
BeanFactory和ApplicationContext的關係
為了更直觀的展示 “低階容器” 和 “高階容器” 的關係,這裡通過常用的ClassPathXmlApplicationContext 類來展示整個容器的層級 UML 關係。
有點複雜?先不要慌,我來解釋一下。
最上面的是 BeanFactory,下面的 3 個綠色的,都是功能擴充套件介面,這裡就不展開講。
看下面的隸屬 ApplicationContext 粉紅色的 “高階容器”,依賴著 “低階容器”,這裡說的是依賴,不是繼承哦。他依賴著 “低階容器” 的 getBean 功能。而高階容器有更多的功能:支援不同的資訊源頭,可以訪問檔案資源,支援應用事件(Observer 模式)。
通常使用者看到的就是 “高階容器”。但 BeanFactory 也非常夠用啦!
左邊灰色區域的是 “低階容器”, 只負載載入 Bean,獲取 Bean。容器其他的高階功能是沒有的。例如上圖畫的 refresh 重新整理 Bean 工廠所有配置,生命週期事件回撥等。
小結
說了這麼多,不知道你有沒有理解Spring IoC?這裡小結一下:IoC 在 Spring 裡,只需要低階容器就可以實現,2 個步驟:
- 載入配置檔案,解析成 BeanDefinition 放在 Map 裡。
- 呼叫 getBean 的時候,從 BeanDefinition 所屬的 Map 裡,拿出 Class 物件進行例項化,同時,如果有依賴關係,將遞迴呼叫 getBean 方法 —— 完成依賴注入。
上面就是 Spring 低階容器(BeanFactory)的 IoC。
至於高階容器 ApplicationContext,他包含了低階容器的功能,當他執行 refresh 模板方法的時候,將重新整理整個容器的 Bean。同時其作為高階容器,包含了太多的功能。一句話,他不僅僅是 IoC。他支援不同資訊源頭,支援 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方法讓容器去決定依賴關係。
依賴注入的基本原則
依賴注入的基本原則是:應用元件不應該負責查詢資源或者其他依賴的協作物件。配置物件的工作應該由IoC容器負責,“查詢資源”的邏輯應該從應用元件的程式碼中抽取出來,交給IoC容器負責。容器全權負責元件的裝配,它會把符合依賴關係的物件通過屬性(JavaBean中的setter)或者是構造器傳遞給需要的物件。
依賴注入有什麼優勢
依賴注入之所以更流行是因為它是一種更可取的方式:讓容器全權負責依賴查詢,受管元件只需要暴露JavaBean的setter方法或者帶引數的構造器或者介面,使容器可以在初始化時組裝物件的依賴關係。其與依賴查詢方式相比,主要優勢為:
- 查詢定位操作與應用程式碼完全無關。
- 不依賴於容器的API,可以很容易地在任何容器以外使用應用物件。
- 不需要特殊的介面,絕大多數物件可以做到完全不必依賴容器。
有哪些不同型別的依賴注入實現方式?
依賴注入是時下最流行的IoC實現方式,依賴注入分為介面注入(Interface Injection),Setter方法注入(Setter Injection)和構造器注入(Constructor Injection)三種方式。其中介面注入由於在靈活性和易用性比較差,現在從Spring4開始已被廢棄。
構造器依賴注入:構造器依賴注入通過容器觸發一個類的構造器來實現的,該類有一系列引數,每個引數代表一個對其他類的依賴。
Setter方法注入:Setter方法注入是容器通過呼叫無參構造器或無參static工廠 方法例項化bean之後,呼叫該bean的setter方法,即實現了基於setter的依賴注入。
構造器依賴注入和 Setter方法注入的區別
兩種依賴方式都可以使用,構造器注入和Setter方法注入。最好的解決方案是用構造器引數實現強制依賴,setter方法實現可選依賴。
Spring Beans
什麼是Spring beans?
Spring beans 是那些形成Spring應用的主幹的java物件。它們被Spring IOC容器初始化,裝配,和管理。這些beans通過容器中配置的後設資料建立。比如,以XML檔案中 的形式定義。
一個 Spring Bean 定義 包含什麼?
一個Spring Bean 的定義包含容器必知的所有配置後設資料,包括如何建立一個bean,它的生命週期詳情及它的依賴。
如何給Spring 容器提供配置後設資料?Spring有幾種配置方式
這裡有三種重要的方法給Spring 容器提供配置後設資料。
- XML配置檔案。
- 基於註解的配置。
- 基於java的配置。
Spring配置檔案包含了哪些資訊
Spring配置檔案是個XML 檔案,這個檔案包含了類資訊,描述瞭如何配置它們,以及如何相互呼叫。
Spring基於xml注入bean的幾種方式
- Set方法注入;
- 構造器注入:①通過index設定引數的位置;②通過type設定引數型別;
- 靜態工廠注入;
- 例項工廠;
你怎樣定義類的作用域?
當定義一個 在Spring裡,我們還能給這個bean宣告一個作用域。它可以通過bean 定義中的scope屬性來定義。如,當Spring要在需要的時候每次生產一個新的bean例項,bean的scope屬性被指定為prototype。另一方面,一個bean每次使用的時候必須返回同一個例項,這個bean的scope 屬性 必須設為 singleton。
解釋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 的作用域是Singleton。使用 prototype 作用域需要慎重的思考,因為頻繁建立和銷燬 bean 會帶來很大的效能開銷。
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應用上下文中的一個典型的生命週期過程。
bean在Spring容器中從建立到銷燬經歷了若干階段,每一階段都可以針對Spring如何管理bean進行個性化定製。
正如你所見,在bean準備就緒之前,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)。
什麼是Spring的內部bean?什麼是Spring inner beans?
在Spring框架中,當一個bean僅被用作另一個bean的屬性時,它能被宣告為一個內部bean。內部bean可以用setter注入“屬性”和構造方法注入“構造引數”的方式來實現,內部bean通常是匿名的,它們的Scope一般是prototype。
在 Spring中如何注入一個java集合?
Spring提供以下幾種集合的配置元素:
型別用於注入一列值,允許有相同的值。
型別用於注入一組值,不允許有相同的值。
型別用於注入一組鍵值對,鍵和值都可以為任意型別。
型別用於注入一組鍵值對,鍵和值都只能為String型別。
什麼是bean裝配?
裝配,或bean 裝配是指在Spring 容器中把bean組裝到一起,前提是容器需要知道bean的依賴關係,如何通過依賴注入來把它們裝配到一起。
什麼是bean的自動裝配?
在Spring框架中,在配置檔案中設定bean的依賴關係是一個很好的機制,Spring 容器能夠自動裝配相互合作的bean,這意味著容器不需要和配置,能通過Bean工廠自動處理bean之間的協作。這意味著 Spring可以通過向Bean Factory中注入的方式自動搞定bean之間的依賴關係。自動裝配可以設定在每個bean上,也可以設定在特定的bean上。
解釋不同方式的自動裝配,spring 自動裝配 bean 有哪些方式?
在spring中,物件無需自己查詢或建立與其關聯的其他物件,由容器負責把需要相互協作的物件引用賦予各個物件,使用autowire來配置自動裝載模式。
在Spring框架xml配置中共有5種自動裝配:
- no:預設的方式是不進行自動裝配的,通過手工設定ref屬性來進行裝配bean。
- byName:通過bean的名稱進行自動裝配,如果一個bean的 property 與另一bean 的name 相同,就進行自動裝配。
- byType:通過引數的資料型別進行自動裝配。
- constructor:利用建構函式進行裝配,並且建構函式的引數通過byType進行裝配。
- autodetect:自動探測,如果有構造方法,通過 construct的方式自動裝配,否則使用 byType的方式自動裝配。
使用@Autowired註解自動裝配的過程是怎樣的?
使用@Autowired註解來自動裝配指定的bean。在使用@Autowired註解之前需要在Spring配置檔案進行配置,<context:annotation-config />。
在啟動spring IoC時,容器自動裝載了一個
AutowiredAnnotationBeanPostProcessor後置處理器,當容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查詢需要的bean,並裝配給該物件的屬性。在使用@Autowired時,首先在容器中查詢對應型別的bean:
如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的資料;
如果查詢的結果不止一個,那麼@Autowired會根據名稱來查詢;
如果上述查詢的結果為空,那麼會丟擲異常。解決方法時,使用required=false。
自動裝配有哪些侷限性?
自動裝配的侷限性是:
重寫:你仍需用 和 配置來定義依賴,意味著總要重寫自動裝配。
基本資料型別:你不能自動裝配簡單的屬性,如基本資料型別,String字串,和類。
模糊特性:自動裝配不如顯式裝配精確,如果有可能,建議使用顯式裝配。
你可以在Spring中注入一個 和一個空字串嗎?可以。
Spring註解
什麼是基於Java的Spring註解配置? 給一些註解的例子
基於Java的配置,允許你在少量的Java註解的幫助下,進行你的大部分Spring配置而非通過XML檔案。
以@Configuration 註解為例,它用來標記類可以當做一個bean的定義,被Spring IOC容器使用。
另一個例子是@Bean註解,它表示此方法將要返回一個物件,作為一個bean註冊進Spring應用上下文。
@Configuration
publicclassStudentConfig{
@Beanpublic StudentBean myStudent {return new StudentBean;}}
怎樣開啟註解裝配?
註解裝配在預設情況下是不開啟的,為了使用註解裝配,我們必須在Spring配置檔案中配置
context:annotation-config/元素。
@Component, @Controller, @Repository, @Service 有何區別?
@Component:這將 java 類標記為 bean。它是任何 Spring 管理元件的通用構造型。spring 的元件掃描機制現在可以將其拾取並將其拉入應用程式環境中。
@Controller:這將一個類標記為 Spring Web MVC 控制器。標有它的 Bean 會自動匯入到 IoC 容器中。
@Service:此註解是元件註解的特化。它不會對 @Component 註解提供任何其他行為。您可以在服務層類中使用 @Service 而不是 @Component,因為它以更好的方式指定了意圖。
@Repository:這個註解是具有類似用途和功能的 @Component 註解的特化。它為 DAO 提供了額外的好處。它將 DAO 匯入 IoC 容器,並使未經檢查的異常有資格轉換為 Spring DataAccessException。
@Required 註解有什麼作用
這個註解表明bean的屬性必須在配置的時候設定,通過一個bean定義的顯式的屬性值或通過自動裝配,若@Required註解的bean屬性未被設定,容器將丟擲
BeanInitializationException。示例:
public classEmployee{
private String name;@RequiredpublicvoidsetName(String name){
this.name=name;}public string getName{return name;}}
@Autowired 註解有什麼作用
@Autowired預設是按照型別裝配注入的,預設情況下它要求依賴物件必須存在(可以設定它required屬性為false)。@Autowired 註解提供了更細粒度的控制,包括在何處以及如何完成自動裝配。它的用法和@Required一樣,修飾setter方法、構造器、屬性或者具有任意名稱和/或多個引數的PN方法。
public classEmployee{
private String name;@AutowiredpublicvoidsetName(String name) {
this.name=name;}public string getName{return name;}}
@Autowired和@Resource之間的區別
@Autowired可用於:建構函式、成員變數、Setter方法
@Autowired和@Resource之間的區別
@Autowired預設是按照型別裝配注入的,預設情況下它要求依賴物件必須存在(可以設定它required屬性為false)。
@Resource預設是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean才會按照型別來裝配注入。
@Qualifier 註解有什麼作用
當您建立多個相同型別的 bean 並希望僅使用屬性裝配其中一個 bean 時,您可以使用@Qualifier 註解和 @Autowired 通過指定應該裝配哪個確切的 bean 來消除歧義。
@RequestMapping 註解有什麼用?
@RequestMapping 註解用於將特定 HTTP 請求方法對映到將處理相應請求的控制器中的特定類/方法。此註釋可應用於兩個級別:
- 類級別:對映請求的 URL
- 方法級別:對映 URL 以及 HTTP 請求方法
Spring資料訪問
解釋物件/關係對映整合模組
Spring 通過提供ORM模組,支援我們在直接JDBC之上使用一個物件/關係對映對映(ORM)工具,Spring 支援整合主流的ORM框架,如Hiberate,JDO和 iBATIS,JPA,TopLink,JDO,OJB 。Spring的事務管理同樣支援以上所有ORM框架及JDBC。
在Spring框架中如何更有效地使用JDBC?
使用Spring JDBC 框架,資源管理和錯誤處理的代價都會被減輕。所以開發者只需寫statements 和 queries從資料存取資料,JDBC也可以在Spring框架提供的模板類的幫助下更有效地被使用,這個模板叫JdbcTemplate
解釋JDBC抽象和DAO模組
通過使用JDBC抽象和DAO模組,保證資料庫程式碼的簡潔,並能避免資料庫資源錯誤關閉導致的問題,它在各種不同的資料庫的錯誤資訊之上,提供了一個統一的異常訪問層。它還利用Spring的AOP 模組給Spring應用中的物件提供事務管理服務。
spring DAO 有什麼用?
Spring DAO(資料訪問物件) 使得 JDBC,Hibernate 或 JDO 這樣的資料訪問技術更容易以一種統一的方式工作。這使得使用者容易在永續性技術之間切換。它還允許您在編寫程式碼時,無需考慮捕獲每種技術不同的異常。
spring JDBC API 中存在哪些類?
- JdbcTemplate
- SimpleJdbcTemplate
- NamedParameterJdbcTemplate
- SimpleJdbcInsert
- SimpleJdbcCall
JdbcTemplate是什麼
JdbcTemplate 類提供了很多便利的方法解決諸如把資料庫資料轉變成基本資料型別或物件,執行寫好的或可呼叫的資料庫操作語句,提供自定義的資料錯誤處理。
使用Spring通過什麼方式訪問Hibernate?使用 Spring 訪問 Hibernate 的方法有哪些?
在Spring中有兩種方式訪問Hibernate:
- 使用 Hibernate 模板和回撥進行控制反轉
- 擴充套件 HibernateDAOSupport 並應用 AOP 攔截器節點
如何通過HibernateDaoSupport將Spring和Hibernate結合起來?
用Spring的 SessionFactory 呼叫 LocalSessionFactory。整合過程分三步:
- 配置the Hibernate SessionFactory
- 繼承HibernateDaoSupport實現一個DAO
- 在AOP支援的事務中裝配
Spring支援的事務管理型別, spring 事務實現方式有哪些?
Spring支援兩種型別的事務管理:
程式設計式事務管理:這意味你通過程式設計的方式管理事務,給你帶來極大的靈活性,但是難維護。
宣告式事務管理:這意味著你可以將業務程式碼和事務管理分離,你只需用註解和XML配置來管理事務。
Spring事務的實現方式和實現原理
Spring事務的本質其實就是資料庫對事務的支援,沒有資料庫的事務支援,spring是無法提供事務功能的。真正的資料庫層的事務提交和回滾是通過binlog或者redo log實現的。
說一下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 條記錄,這就好像產生了幻覺。發生幻讀的原因也是另外一個事務新增或者刪除或者修改了第一個事務結果集裡面的資料,同一個記錄的資料內容被修改了,所有資料行的記錄就變多或者變少了。
Spring框架的事務管理有哪些優點?
- 為不同的事務API 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一個不變的程式設計模式。
- 為程式設計式事務管理提供了一套簡單的API而不是一些複雜的事務API
- 支援宣告式事務管理。
- 和Spring各種資料訪問抽象層很好得整合。
你更傾向用那種事務管理型別?
大多數Spring框架的使用者選擇宣告式事務管理,因為它對應用程式碼的影響最小,因此更符合一個無侵入的輕量級容器的思想。宣告式事務管理要優於程式設計式事務管理,雖然比程式設計式事務管理(這種方式允許你通過程式碼控制事務)少了一點靈活性。唯一不足地方是,最細粒度只能作用到方法級別,無法做到像程式設計式事務那樣可以作用到程式碼塊級別。
Spring面向切面程式設計(AOP)
什麼是AOP
OOP(Object-Oriented Programming)物件導向程式設計,允許開發者定義縱向的關係,但並適用於定義橫向的關係,導致了大量程式碼的重複,而不利於各個模組的重用。
AOP(Aspect-Oriented Programming),一般稱為面向切面程式設計,作為物件導向的一種補充,用於將那些與業務無關,但卻對多個物件產生影響的公共行為和邏輯,抽取並封裝為一個可重用的模組,這個模組被命名為“切面”(Aspect),減少系統中的重複程式碼,降低了模組間的耦合度,同時提高了系統的可維護性。可用於許可權認證、日誌、事務處理等。
Spring AOP and AspectJ AOP 有什麼區別?AOP 有哪些實現方式?
AOP實現的關鍵在於 代理模式,AOP代理主要分為靜態代理和動態代理。靜態代理的代表為AspectJ;動態代理則以Spring AOP為代表。
(1)AspectJ是靜態代理的增強,所謂靜態代理,就是AOP框架會在編譯階段生成AOP代理類,因此也稱為編譯時增強,他會在編譯階段將AspectJ(切面)織入到Java位元組碼中,執行的時候就是增強之後的AOP物件。
(2)Spring AOP使用的動態代理,所謂的動態代理就是說AOP框架不會去修改位元組碼,而是每次執行時在記憶體中臨時為方法生成一個AOP物件,這個AOP物件包含了目標物件的全部方法,並且在特定的切點做了增強處理,並回撥原物件的方法。
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做動態代理的。
靜態代理與動態代理區別在於生成AOP代理物件的時機不同,相對來說AspectJ的靜態代理方式具有更好的效能,但是AspectJ需要特定的編譯器進行處理,而Spring AOP則無需特定的編譯器處理。
InvocationHandler 的 invoke(Object proxy,Method method,Object[] args):proxy是最終生成的代理例項; method 是被代理目標例項的某個具體方法; args 是被代理目標例項某個方法的具體入參, 在方法反射呼叫時使用。
如何理解 Spring 中的代理?
將 Advice 應用於目標物件後建立的物件稱為代理。在客戶端物件的情況下,目標物件和代理物件是相同的。
Advice + Target Object = Proxy
解釋一下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在執行時通知物件
通過在代理類中包裹切面,Spring在執行期把切面織入到Spring管理的bean中。代理封裝了目標類,並攔截被通知方法的呼叫,再把呼叫轉發給真正的目標bean。當代理攔截到方法呼叫時,在呼叫目標bean方法之前,會執行切面邏輯。
直到應用需要被代理的bean時,Spring才建立代理物件。如果使用的是ApplicationContext的話,在ApplicationContext從BeanFactory中載入所有bean的時候,Spring才會建立被代理的物件。因為Spring執行時才建立代理物件,所以我們不需要特殊的編譯器來織入SpringAOP的切面。
Spring只支援方法級別的連線點
因為Spring基於動態代理,所以Spring只支援方法連線點。Spring缺少對欄位連線點的支援,而且它不支援構造器連線點。方法之外的連線點攔截功能,我們可以利用Aspect來補充。
在Spring AOP 中,關注點和橫切關注的區別是什麼?在 spring aop 中 concern 和 cross-cutting concern 的不同之處 關注點(concern)是應用中一個模組的行為,一個關注點可能會被定義成一個我們想實現的一個功能。
橫切關注點(cross-cutting concern)是一個關注點,此關注點是整個應用都會使用的功能,並影響整個應用,比如日誌,安全和資料傳輸,幾乎應用的每個模組都需要的功能。因此這些都屬於橫切關注點。
Spring通知有哪些型別?
在AOP術語中,切面的工作被稱為通知,實際上是程式執行時要通過SpringAOP框架觸發的程式碼段。
Spring切面可以應用5種型別的通知:
- 前置通知(Before):在目標方法被呼叫之前呼叫通知功能;
- 後置通知(After):在目標方法完成之後呼叫通知,此時不會關心方法的輸出是什麼;
- 返回通知(After-returning ):在目標方法成功執行之後呼叫通知;
- 異常通知(After-throwing):在目標方法丟擲異常後呼叫通知;
- 環繞通知(Around):通知包裹了被通知的方法,在被通知的方法呼叫之前和呼叫之後執行自定義的行為。
同一個aspect,不同advice的執行順序:
①沒有異常情況下的執行順序:
around before advice
before advicetarget method 執行around after adviceafter adviceafterReturning
②有異常情況下的執行順序:
around before advice
before advicetarget method 執行around after adviceafter adviceafterThrowing:異常發生java.lang.RuntimeException: 異常發生
什麼是切面 Aspect?
aspect 由 pointcount 和 advice 組成,切面是通知和切點的結合。它既包含了橫切邏輯的定義, 也包括了連線點的定義. Spring AOP 就是負責實施切面的框架, 它將切面所定義的橫切邏輯編織到切面所指定的連線點中. AOP 的工作重心在於如何將增強編織目標物件的連線點上, 這裡包含兩個工作:
- 如何通過 pointcut 和 advice 定位到特定的 joinpoint 上
- 如何在 advice 中編寫切面程式碼.
可以簡單地認為, 使用 @Aspect 註解的類就是切面.
解釋基於XML Schema方式的切面實現
在這種情況下,切面由常規類以及基於XML的配置實現。
解釋基於註解的切面實現
在這種情況下(基於@AspectJ的實現),涉及到的切面宣告的風格與帶有java5標註的普通java類一致。
有幾種不同型別的自動代理?
- BeanNameAutoProxyCreator
- DefaultAdvisorAutoProxyCreator
- Metadata autoproxying
資料領取
本文就先寫到這裡,面試中常問的一些題目我都有整理的,後面會持續更新,需要PDF的好兄弟可以點贊本文+關注後【點選此處】即可領取