前言:
又到了金九銀十的日子,前幾天好朋友發來喜訊,跳槽一個月了,面試了有二十家公司,在面試官的狂轟濫炸下終於拿到了不錯的offer。但是比較可惜的是朋友內推的大廠面試失敗了,而且還是在Spring上,就令人挺無語的。他說本來以為大廠的面試會問一下高並發線程組件方面的知識,所以就著重看了一下這些,沒想到栽倒了Spring上,真是太慘了!
所以今天就總結一下幾個關於Spring的高頻面試題,比如:SpringAOP和aspectJ AOP有什麼區別?springbean的生命周期?事務控制等,希望對大家有所幫助。
IOC
IOC(Inversion Of Controll,控制反轉)是一種設計思想,將原本在程序中手動創建對象的控制權,交由給Spring框架來管理。IOC容器是Spring用來實現IOC的載體,IOC容器實際上就是一個Map(key, value),Map中存放的是各種對象。
這樣可以很大程度上簡化應用的開發,把應用從複雜的依賴關係中解放出來。IOC容器就像是一個工廠,當需要創建一個對象,只需要配置好配置文件/註解即可,不用考慮對象是如何被創建出來的,大大增加了項目的可維護性且降低了開發難度。
AOP
AOP(Aspect-Oriented Programming,面向切面編程)能夠將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任(例如事務處理、日誌管理、權限控制等)封裝起來,便於減少系統的重複代碼,降低模塊間的耦合度,並有利於未來的可擴展性和可維護性。使用AOP之後我們可以把一些通用功能抽象出來,在需要用到的地方直接使用即可,這樣可以大大簡化代碼量,提高了系統的擴展性。
Spring AOP是基於動態代理的,如果要代理的對象實現了某個接口,那麼Spring AOP就會使用JDK動態代理去創建代理對象;而對於沒有實現接口的對象,就無法使用JDK動態代理,轉而使用CGlib動態代理生成一個被代理對象的子類來作為代理。
Spring AOP / AspectJ AOP 的區別?
Spring AOP屬於運行時增強,而AspectJ是編譯時增強。
Spring AOP基於代理(Proxying),而AspectJ基於字節碼操作(Bytecode Manipulation)。
AspectJ相比於Spring AOP功能更加強大,但是Spring AOP相對來說更簡單。如果切面比較少,那麼兩者性能差異不大。但是,當切面太多的話,最好選擇AspectJ,它比SpringAOP快很多。
Spring框架中都用到了哪些設計模式?
代理模式:在AOP和remoting中被用得比較多。單例模式:在spring配置文件中定義的bean默認為單例模式。模板方法模式:用來解決代碼重複的問題。前端控制器模式:Spring提供了DispatcherServlet來對請求進行分發。依賴注入模式:貫穿於BeanFactory / ApplicationContext接口的核心理念。工廠模式:BeanFactory用來創建對象的實例。Spring MVC的核心是什麼,請求的流程是怎麼處理的,控制反轉怎麼實現的
核心:控制反轉和面向切面
請求處理流程:
首先用戶發送請求到前端控制器,前端控制器根據請求信息(如URL)來決定選擇哪一個頁面控制器進行處理並把請求委託給它,即以前的控制器的控制邏輯部分;頁面控制器接收到請求後,進行功能處理,首先需要收集和綁定請求參數到一個對象,並進行驗證,然後將命令對象委託給業務對象進行處理;處理完畢後返回一個ModelAndView(模型數據和邏輯視圖名);前端控制器收回控制權,然後根據返回的邏輯視圖名,選擇相應的視圖進行渲染,並把模型數據傳入以便視圖渲染;前端控制器再次收回控制權,將響應返回給用戶。控制反轉如何實現:
我們每次使用spring框架都要配置xml文件,這個xml配置了bean的id和class。spring中默認的bean為單實例模式,通過bean的class引用反射機制可以創建這個實例。因此,spring框架通過反射替我們創建好了實例並且替我們維護他們。A需要引用B類,spring框架就會通過xml把B實例的引用傳給了A的成員變量。
你用過哪些重要的 Spring 註解?
@Controller - 用於 Spring MVC 項目中的控制器類。
@Service - 用於服務類。
@RequestMapping - 用於在控制器處理程序方法中配置 URI 映射。
@ResponseBody - 用於發送 Object 作為響應,通常用於發送 XML 或 JSON 數據作為響應。
@PathVariable - 用於將動態值從 URI 映射到處理程序方法參數。
@Autowired - 用於在 spring bean 中自動裝配依賴項。
@Qualifier - 使用 @Autowired 註解,以避免在存在多個 bean 類型實例時出現混淆。
@Scope - 用於配置 spring bean 的範圍。
@Configuration,@ComponentScan 和 @Bean - 用於基於 java 的配置。
@Aspect,@Before,@After,@Around,@Pointcut - 用於切面編程(AOP)。
@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。
SpringMVC 流程?
1)用戶發送請求至前端控制器 DispatcherServlet。2)DispatcherServlet 收到請求調用 HandlerMapping 處理器映射器。3)處理器映射器找到具體的處理器(可以根據 xml 配置、註解進行查找),生成處理器及處理器攔截器(如果有則生成)一併返回給 DispatcherServlet。4)DispatcherServlet 調用 HandlerAdapter 處理器適配器。5)HandlerAdapter 經過適配調用具體的處理器(Controller,也叫後端控制器)6)Controller 執行完成返回 ModelAndView。7)HandlerAdapter 將 controller 執行結果 ModelAndView 返回給 DispatcherServlet。8)DispatcherServlet 將 ModelAndView 傳給 ViewReslover 視圖解析器。9)ViewReslover 解析後返回具體 View。10)DispatcherServlet 根據 View 進行渲染視圖(即將模型數據填充至視圖中)。11)DispatcherServlet 響應用戶。
SpringMvc 怎麼和 AJAX 相互調用的?
通過 Jackson 框架就可以把 Java 裡面的對象直接轉化成 Js 可以識別的 Json 對象具體步驟如下:
加入 Jackson.jar在配置文件中配置 json 的映射在接受 Ajax 方法裡面可以直接返回 Object,List 等,但方法前面要加上@ResponseB註解有哪些不同類型的依賴注入實現方式?
依賴注入是時下最流行的IoC實現方式,依賴注入分為接口注入(Interface Injection),Setter方法注入(Setter Injection)和構造器注入(Constructor Injection)三種方式。其中接口注入由於在靈活性和易用性比較差,現在從Spring4開始已被廢棄。
構造器依賴注入:構造器依賴注入通過容器觸發一個類的構造器來實現的,該類有一系列參數,每個參數代表一個對其他類的依賴。
Setter方法注入:Setter方法注入是容器通過調用無參構造器或無參static工廠 方法實例化bean之後,調用該bean的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設置參數類型;靜態工廠注入;實例工廠;
關於事務控制
事務是一系列的動作,它們綜合在一起才是一個完整的工作單元,這些動作必須全部完成,如果有一個失敗的話,那麼事務就會回滾到最開始的狀態,仿佛什麼都沒發生過一樣。
1.1 spring中事務控制APIPlatformTransactionManager 接口提供事務操作的方法,包含三個具體的操作
spring中事務控制接口的結構
1.1.2 TransactionDefinition
事務的定義信息對象,包含如下方法:
獲取事務對象名稱:String getName()
獲取事務隔離級別:int getIsolationLevel()
獲取事務傳播行為:int getPropagationBehavior()
獲取事務超時時間:int getTimeout()
獲取事務是否只讀:boolean isReadOnly()
1.1.3 TransactionStatus
描述了某個時間點上事務對象的狀態信息,包含6個具體的操作:
刷新事務:void flush()
獲取是否存在儲存點:boolean hasSavepoint()
獲取事務是否完成:boolean isCompleted()
獲取事務是否為新的事物:boolean isNewTransaction()
獲取事務是否回滾:boolean isRollbackOnly()
設置事務回滾:void set RollbackOnly()
1.2 事務的隔離級別
事務的隔離界別反映事務提交並發訪問時的處理態度
1.2.1 事務隔離的級別
ISOLATION_DEFAULT 默認級別,由 DBA 默認的設置來決定隔離級別,歸屬下列某一種ISOLATION_READ_UNCOMMITTED 就是一個事務可以讀取另一個未提交事務的數據。會出現髒讀、不可重複讀、幻讀(隔離級別最低,但並發性高)ISOLATION_READ_COMMITTED 就是一個事務要等另一個事務提交後才能讀取數據,解決髒讀問題。會出現不可重複讀、幻讀問題(鎖定正在讀取的行,適用於大多數系統,Oracle默認級別)ISOLATION_REPEATABLE_READ 就是在開始讀取數據(事務開啟)時,不再允許修改操作,解決不可重複讀問題。會出現幻讀問題(鎖定所讀的所有行,MYSQL默認級別)ISOLATION_SERALZABLE 是最高的事務隔離級別,在該級別下,事務串行化順序執行,可以避免髒讀、不可重複讀與幻讀。但是這種事務隔離級別效率低下,比較耗資料庫性能,一般不使用。
1.2.2 資料庫讀取時會出現的三種問題
① Dirty reads:讀髒數據。
也就是說,比如事務A的未提交(還依然緩存)的數據被事務B讀走,如果事務A失敗回滾,會導致事務B所讀取的的數據是錯誤的。
② non-repeatable reads:數據不可重複讀。
比如事務A中兩處讀取數據price的值。在第一讀的時候,price是100,然後事務B就把price的值改成 200;事務A再讀一次,結果就發現,price竟然就變成200了,造成事務A數據混亂。
③ phantom reads:幻象讀數據。
這個和non-repeatable reads相似,也是同一個事務中多次讀不一致的問題。但是 non-repeatable reads 的不一致是因為他所要取的數據值被改變了(比如price)而 phantom reads 所要讀的數據的不一致卻是他的條件數據集發生變化了。
比如:執行 Select account.id where account.name=「Bruce*」,第一次讀去了6個符合條件的id;第二次讀取的時候,由於事務B把一個帳號的名字由"dd"改成"Bruce1",結果取出來了7個數據。
1.2.3 數據隔離級別和出現的問題之間的關聯
1.3 事務的傳播行為
REQUIRED:如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。一般的選 擇(默認值)SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方式執行(沒有事務)MANDATORY:使用當前的事務,如果當前沒有事務,就拋出異常。REQUERS_NEW:新建事務,如果當前在事務中,把當前事務掛起。NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。NEVER:以非事務方式運行,如果當前存在事務,拋出異常。NESTED:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行REQUIRED類似的操作。1.4 超時時間
指事務提交後最長可以等待的時間,超出時間則會自動失敗。默認值是-1,沒有時間限制。如果有,則以秒為單位進行設置。
1.5 是否為只讀事務
讀寫型事務:增加、刪除、修改時開啟事務
只讀型事務:執行查詢時,也會開啟事務
面試總結:
無論是哪家公司,都很重視Spring框架技術,重視基礎,所以千萬別小看任何知識。面試是一個雙向選擇的過程,不要抱著畏懼的心態去面試,不利於自己的發揮。同時看中的應該不止薪資,還要看你是不是真的喜歡這家公司,是不是能真的得到鍛鍊。其實我寫了這麼多,只是我自己的總結,並不一定適用於所有人,相信經過一些面試,大家都會有這些感觸。
另外整理多個項目練習題,以及各種Java核心知識點免費分享給大家,下方只是部分截圖,需要的話想要資料的話可以下方評論,或者私聊~