天天看點

Spring架構常見經典面試題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才會按照類型來裝配注入。