Spring框架常見經典面試題

Spring框架常用經典面試題


1. Spring 是什麼? 使用Spring框架的好處是什麼?

  • Spring 是個java企業級應用的開源開發框架。Spring主要用來開發Java應用,但是有些擴展是針對構建J2EE平臺的web應用。Spring 框架目標是簡化Java企業級應用開發,並通過POJO爲基礎的編程模型促進良好的編程習慣
  • **輕量:**Spring 是輕量的,基本的版本大約2MB。
  • **控制反轉:**Spring通過控制反轉實現了鬆散耦合,對象們給出它們的依賴,而不是創建或查找依賴的對象們。
  • **面向切面的編程(AOP):**Spring支持面向切面的編程,並且把應用業務邏輯和系統服務分開。
  • **容器:**Spring 包含並管理應用中對象的生命週期和配置。
  • MVC框架:Spring的WEB框架是個精心設計的框架,是Web框架的一個很好的替代品。
  • **事務管理:**Spring 提供一個持續的事務管理接口,可以擴展到上至本地事務下至全局事務(JTA)。
  • **異常處理:**Spring 提供方便的API把具體技術相關的異常(比如由JDBC,Hibernate or JDO拋出的)轉化爲一致的unchecked 異常。

2. Spring 中AOP和IOC的概念以及在spring中是如何應用的?

  • AOP Aspect Oriented Program,面向(方面)切面的編程;
    • AOP方式很類似filter,就是在程序正常的業務流中間像切面一樣插入很多其他需要執行的代碼,比如登錄時候,在進入登錄頁面前寫入日誌,很常用的,尤其是跟數據庫有關的,或者跟支付有關的程序肯定會在每一步前面插入日誌。面向方面的編程,即 AOP,是一種編程技術,它允許程序員對橫切關注點或橫切典型的職責分界線的行爲(例如日誌和事務管理)進行模塊化。AOP 的核心構造是切面,它將那些影響多個類的行爲封裝到可重用的模塊中。
    • AOP Advice(AOP通知)分爲: 前置通知 後置通知 異常通知 環繞通知
  • IOC Invert Of Control,控制反轉。
    • 簡單說一下,IOC就是其實就是依賴注入,即用接口編程,在程序中不出現new關鍵字,而是用接口來命名引用,然後通過某種方式把接口的某個實現類的實例注入到引用裏,從而實現接口與具體實現類的松耦合。由容器控制程序之間的關係(通過XML配置),而非傳統實現中的由程序代碼直接操控,(在一個Class對象中引用另一個Class對象時,我們通常都是直接通過new contructor)。控制權由應用代碼中轉到了外部容器,控制權的轉移,是所謂的反轉。
    • 有哪些不同類型的IOC(依賴注入)方式?
      • **構造器依賴注入:**構造器依賴注入通過容器觸發一個類的構造器來實現的,該類有一系列參數,每個參數代表一個對其他類的依賴。
      • **Setter方法注入:**Setter方法注入是容器通過調用無參構造器或無參static工廠 方法實例化bean之後,調用該bean的setter方法,即實現了基於setter的依賴注入。
      • 兩種依賴方式都可以使用,構造器注入和Setter方法注入。最好的解決方案是用構造器參數實現強制依賴,setter方法實現可選依賴。

3. Spring 如何處理線程併發問題?

Spring使用ThreadLocal解決線程安全問題

​ 我們知道在一般情況下,只有無狀態的Bean纔可以在多線程環境下共享,在Spring中,絕大部分Bean都可以聲明爲singleton作用域。就是因爲Spring對一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非線程安全狀態採用ThreadLocal進行處理,讓它們也成爲線程安全的狀態,因爲有狀態的Bean就可以在多線程中共享了。

ThreadLocal和線程同步機制都是爲了解決多線程中相同變量的訪問衝突問題。

​ 在同步機制中,通過對象的鎖機制保證同一時間只有一個線程訪問變量。這時該變量是多個線程共享的,使用同步機制要求程序慎密地分析什麼時候對變量進行讀寫,什麼時候需要鎖定某個對象,什麼時候釋放對象鎖等繁雜的問題,程序設計和編寫難度相對較大。

​ 而ThreadLocal則從另一個角度來解決多線程的併發訪問。ThreadLocal會爲每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問衝突。因爲每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。

​ 由於ThreadLocal中可以持有任何類型的對象,低版本JDK所提供的get()返回的是Object對象,需要強制類型轉換。但JDK5.0通過泛型很好的解決了這個問題,在一定程度地簡化ThreadLocal的使用。

​ 概括起來說,對於多線程資源共享的問題,同步機制採用了“以時間換空間”的方式,而ThreadLocal採用了“以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊訪問,而後者爲每一個線程都提供了一份變量,因此可以同時訪問而互不影響。


4. Spring Bean的作用域之間有什麼區別?

Spring容器中的bean可以分爲5個範圍。

**singleton:**這種bean範圍是默認的,這種範圍確保不管接受到多少個請求,每個容器中只有一個bean的實例,單例的模式由bean factory自身來維護。
**prototype:**原形範圍與單例範圍相反,爲每一個bean請求提供一個實例。
**request:**在請求bean範圍內會每一個來自客戶端的網絡請求創建一個實例,在請求完成以後,bean會失效並被垃圾回收器回收。
**Session:**與請求範圍類似,確保每個session中有一個bean的實例,在session過期後,bean會隨之失效。
**global-session:**global-session和Portlet應用相關。當你的應用部署在Portlet容器中工作時,它包含很多portlet。如果你想要聲明讓所有的portlet共用全局的存儲變量的話,那麼這全局變量需要存儲在global-session中。
全局作用域與Servlet中的session作用域效果相同。


5. Spring 的事物有幾種方式? 區別是什麼?

  • 聲明式事務
    • 使用spring聲明式事務,spring使用AOP來支持聲明式事務,會根據事務屬性,自動在方法調用之前決定是否開啓一個事務,並在方法執行之後決定事務提交或回滾事務。做法是在a方法外圍添加註解或者直接在配置文件中定義,a方法需要事務處理,在spring中會通過配置文件在a方法前後攔截,並添加事務.
  • 編程式事務:
    • 編程式事務需要你在代碼中直接加入處理事 務的邏輯,可能需要在代碼中顯式調用beginTransaction()、commit()、rollback()等事務管理相關的方法,如在執行a方 法時候需要事務處理,你需要在a方法開始時候開啓事務,處理完後。在方法結束時候,關閉事務.
  • 區別: 編程式事務侵入性比較強,但處理粒度更細

6. Spring 中事物的特性有哪些?

  • 原子性(Atomicity)
    • 原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,因此事務的操作如果成功就必須要完全應用到數據庫,如果操作失敗則不能對數據庫有任何影響。
  • 一致性(Consistency)
    • 一致性是指事務必須使數據庫從一個一致性狀態變換到另一個一致性狀態,也就是說一個事務執行之前和執行之後都必須處於一致性狀態。拿轉賬來說,假設用戶A和用戶B兩者的錢加起來一共是5000,那麼不管A和B之間如何轉賬,轉幾次賬,事務結束後兩個用戶的錢相加起來應該還得是5000,這就是事務的一致性。
  • 隔離性(Isolation)
    • 隔離性是當多個用戶併發訪問數據庫時,比如操作同一張表時,數據庫爲每一個用戶開啓的事務,不能被其他事務的操作所幹擾,多個併發事務之間要相互隔離。即要達到這麼一種效果:對於任意兩個併發的事務T1和T2,在事務T1看來,T2要麼在T1開始之前就已經結束,要麼在T1結束之後纔開始,這樣每個事務都感覺不到有其他事務在併發地執行。
  • 持久性(Durability)
    • 持久性是指一個事務一旦被提交了,那麼對數據庫中的數據的改變就是永久性的,即便是在數據庫系統遇到故障的情況下也不會丟失提交事務的操作。

7. Spring 工作機制及爲什麼要用?

Spring 是一個開源框架,是爲了解決企業應用程序開發複雜性而創建的。Spring既是一個AOP框架,也是一IOC容器。

SpringFramework的組成:Spring AOP,Spring DAO,Spring ORM,Spring Web,Spring Context, Spring Web MVC。

Spring的核心就是IOC和AOP,所以Spring的工作機制簡單的理解也就是IOC和AOP的工作機制。

藉助於Spring AOP,Spring IoC能夠很方便的使用到非常健壯、靈活的企業級服務,通過使用IoC能夠降低組件之間的耦合度,最終,能夠提高類的重用性,利於測試,而且更利於整個產品或系統集成和配置。


9. Spring 中的BeanFactory和ApplicationContext的區別?

BeanFactory 可以理解爲含有bean集合的工廠類。BeanFactory 包含了種bean的定義,以便在接收到客戶端請求時將對應的bean實例化。
BeanFactory還能在實例化對象的時生成協作類之間的關係。此舉將bean自身與bean客戶端的配置中解放出來。BeanFactory還包含了bean生命週期的控制,調用客戶端的初始化方法(initialization methods)和銷燬方法(destruction methods)。
從表面上看,application context如同bean factory一樣具有bean定義、bean關聯關係的設置,根據請求分發bean的功能。但application context在此基礎上還提供了其他的功能。

  1. 提供了支持國際化的文本消息
  2. 統一的資源文件讀取方式
  3. 已在監聽器中註冊的bean的事件
    以下是三種較常見的 ApplicationContext 實現方式:
    1、ClassPathXmlApplicationContext:從classpath的XML配置文件中讀取上下文,並生成上下文定義。應用程序上下文從程序環境變量中取得。
    ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);
    2、FileSystemXmlApplicationContext :由文件系統中的XML配置文件讀取上下文。
    ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);
    3、XmlWebApplicationContext:由Web應用的XML文件讀取上下文。

10. Spring 的優點和缺點?

  • Spring的優點:
    • Spring能有效地組織你的中間層對象,不管你是否選擇使用了EJB;
    • Spring能消除在許多工程中常見的對Singleton的過多使用。(因爲它降低了系統的可測試性和麪向對象的程度);
    • 通過一種在不同應用程序和項目間一致的方法來處理配置文件,Spring能消除各種各樣自定義格式的屬性文件的需要。Inversion of Control的使用幫助完成了這種簡化;
    • 通過把對接口編程而不是對類編程的代價幾乎減少到沒有,Spring能夠促進養成好的編程習慣;
    • Spring被設計爲讓使用它創建的應用盡可能少的依賴於他的APIs。在Spring應用中的大多數業務對象沒有依賴於Spring;
    • 使用Spring構建的應用程序易於單元測試;
    • Spring能使EJB的使用成爲一個實現選擇,而不是應用架構的必然選擇。你能選擇用POJOs或local EJBs來實現業務接口,卻不會影響調用代碼;
    • Spring幫助你解決許多問題而無需使用EJB。Spring能提供一種EJB的替換物,他們適用於許多web應用。例如:Spring能使用AOP提供聲明性事務管理而不通過EJB容器;
    • Spring爲數據存取提供了一個一致的框架不論使用的是JDBC還是O/R mapping產品;
  • 9.2 Spring的缺點:
    • 使用人數不多,jsp中要寫很多代碼;
    • 控制器過於靈活,缺少一個公用控制器。

11. Spring 框架中的單例Beans是線程安全的麼?

  • Spring框架並沒有對單例bean進行任何多線程的封裝處理。關於單例bean的線程安全和併發問題需要開發者自行去搞定。但實際上,大部分的Spring bean並沒有可變的狀態(比如Serview類和DAO類),所以在某種程度上說Spring的單例bean是線程安全的。如果你的bean有多種狀態的話(比如 View Model 對象),就需要自行保證線程安全。最淺顯的解決辦法就是將多態bean的作用域由“singleton”變更爲“prototype”。

12. Spring 如何保證 Controller 併發的安全?

  • Spring 多線程請求過來調用的Controller對象都是一個,而不是一個請求過來就創建一個Controller對象。
  • 併發的安全? 原因就在於Controller對象是單例的,那麼如果不小心在類中定義了類變量,那麼這個類變量是被所有請求共享的,這可能會造成多個請求修改該變量的值,出現與預期結果不符合的異常
  • 那有沒有辦法讓Controller不以單例而以每次請求都重新創建的形式存在呢
    • 答案是當然可以,只需要在類上添加註解@Scope(“prototype”)即可,這樣每次請求調用的類都是重新生成的(每次生成會影響效率)雖然這樣可以解決問題,但增加了時間成本,總讓人不爽,還有其他方法麼?答案是肯定的!使用ThreadLocal來保存類變量,將類變量保存在線程的變量域中,讓不同的請求隔離開來。

13. Spring 框架中都用到了哪些設計模式?舉例說明

  • 代理模式 在AOP和remoting中被用的比較多。
  • 單例模式 在spring配置文件中定義的bean默認爲單例模式。
  • 模板方法 用來解決代碼重複的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。
  • 前端控制器 Spring提供了DispatcherServlet來對請求進行分發。
  • 視圖幫助 Spring提供了一系列的JSP標籤,高效宏來輔助將分散的代碼整合在視圖裏。
  • 依賴注入 貫穿於BeanFactory / ApplicationContext接口的核心理念。
  • 工廠模式 BeanFactory用來創建對象的實例。
  • 適配器 spring aop
  • 觀察者 spring 事件驅動模型

14. Spring 有兩種代理方式:

  • 若目標對象實現了若干接口,spring使用JDK的java.lang.reflect.Proxy類代理。
    • 優點:因爲有接口,所以使系統更加松耦合
    • 缺點:爲每一個目標類創建接口
  • 若目標對象沒有實現任何接口,spring使用CGLIB庫生成目標對象的子類。
    • 優點:因爲代理類與目標類是繼承關係,所以不需要有接口的存在。
      缺點:因爲沒有使用接口,所以系統的耦合性沒有使用JDK的動態代理好

15. Spring 框架中自動裝配方式有哪幾種?

  • 基於xml形式:

    • no:默認的方式是不進行自動裝配的,通過手工設置ref屬性來進行裝配bean。
    • byName:通過bean的名稱進行自動裝配 如果一個bean的 property 與另一bean 的name 相同 就進行自動裝配。
    • byType:通過參數的數據類型進行自動裝配。
    • constructor:利用構造函數進行裝配,並且構造函數的參數通過byType進行裝配。
    • autodetect:自動探測,如果有構造方法,通過 construct的方式自動裝配,否則使用 byType的方式自動裝配。
  • 基於註解形式

    • 使用@Autowired註解來自動裝配指定的bean。

      在使用@Autowired註解之前需要在Spring配置文件進行配置,<context:annotation-config />。在啓動spring IoC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor後置處理器,當容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查找需要的bean,並裝配給該對象的屬性。在使用@Autowired時,首先在容器中查詢對應類型的bean:

    • 如果查詢結果剛好爲一個,就將該bean裝配給@Autowired指定的數據;

      如果查詢的結果不止一個,那麼@Autowired會根據名稱來查找;

      如果上述查找的結果爲空,那麼會拋出異常。解決方法時,使用required=false。

    @Autowired //可用於:構造函數、成員變量、Setter方法
    
    //注:@Autowired和@Resource之間的區別
    @Autowired//默認是按照類型裝配注入的,默認情況下它要求依賴對象必須存在(可以設置它required屬性爲false)。
    @Resource//默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean纔會按照類型來裝配注入。
    

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