2020 阿里最新版春招Spring面試題

###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)(13)
#####什麼是Spring IOC 容器?
控制反轉即IoC (Inversion of Control),它把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的“控制反轉”概念就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。

Spring IOC 負責創建對象,管理對象(通過依賴注入(DI),裝配對象,配置對象,並且管理這些對象的整個生命週期。

#####控制反轉(IoC)有什麼作用
管理對象的創建和依賴關係的維護。對象的創建並不是一件簡單的事,在對象關係比較複雜時,如果依賴關係需要程序猿來維護的話,那是相當頭疼的

解耦,由容器去維護具體的對象

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

#####IOC的優點是什麼?
IOC 或 依賴注入把應用的代碼量降到最低。
它使應用容易測試,單元測試不再需要單例和JNDI查找機制。
最小的代價和最小的侵入性使鬆散耦合得以實現。
IOC容器支持加載服務時的餓漢式初始化和懶加載。
#####Spring IoC 的實現機制
Spring 中的 IoC 的實現原理就是工廠模式加反射機制。

示例:

#####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中注入一個null 和一個空字符串嗎?
可以。

###Spring註解
#####什麼是基於Java的Spring註解配置? 給一些註解的例子
基於Java的配置,允許你在少量的Java註解的幫助下,進行你的大部分Spring配置而非通過XML文件。

以@Configuration 註解爲例,它用來標記類可以當做一個bean的定義,被Spring IOC容器使用。

另一個例子是@Bean註解,它表示此方法將要返回一個對象,作爲一個bean註冊進Spring應用上下文。

#####怎樣開啓註解裝配?
註解裝配在默認情況下是不開啓的,爲了使用註解裝配,我們必須在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。示例:

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

#####@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如何處理這些事務的行爲。

#####說一下 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則無需特定的編譯器處理。

#####如何理解 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 advice
target method 執行
around after advice
after advice
afterReturning

②有異常情況下的執行順序:

around before advice
before advice
target method 執行
around after advice
after advice
afterThrowing:異常發生
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

最後,本文內容已整理成文檔《Java核心面試點整理.pdf》,該文檔覆蓋了JVM、鎖、高併發、Spring原理、微服務、Zookeeper、數據庫、數據結構等等。
私信面試 獲取免費領取方式。

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