Spring Boot 面試,一個問題就幹趴下了!

前言

隨着 Spring Boot 使用越來越廣泛,Spring Boot 已經成爲 Java 程序員面試的知識點,很多同學對 Spring Boot 理解不是那麼深刻,經常就會被幾個連環跑給幹趴下了!

比如下面這一段的 Spring Boot 問答:

問:你覺得 Spring Boot 最大的優勢是什麼呢?

答:Spring Boot 的最大的優勢是“約定優於配置“。“約定優於配置“是一種軟件設計範式,開發人員按照約定的方式來進行編程,可以減少軟件開發人員需做決定的數量,獲得簡單的好處,而又不失靈活性。

問:Spring Boot 中 “約定優於配置“的具體產品體現在哪裏。

答:Spring Boot Starter、Spring Boot Jpa 都是“約定優於配置“的一種體現。都是通過“約定優於配置“的設計思路來設計的,Spring Boot Starter 在啓動的過程中會根據約定的信息對資源進行初始化;Spring Boot Jpa 通過約定的方式來自動生成 Sql ,避免大量無效代碼編寫。具體詳細可以參考:Spring Boot 爲什麼這麼火?

問:Spring Boot Starter 的工作原理是什麼?

答:Spring Boot 在啓動的時候會幹這幾件事情:

  • ① Spring Boot 在啓動時會去依賴的 Starter 包中尋找 resources/META-INF/spring.factories 文件,然後根據文件中配置的 Jar 包去掃描項目所依賴的 Jar 包。

  • ② 根據 spring.factories 配置加載 AutoConfigure 類

  • ③ 根據 @Conditional 註解的條件,進行自動配置並將 Bean 注入 Spring Context

總結一下,其實就是 Spring Boot 在啓動的時候,按照約定去讀取 Spring Boot Starter 的配置信息,再根據配置信息對資源進行初始化,並注入到 Spring 容器中。這樣 Spring Boot 啓動完畢後,就已經準備好了一切資源,使用過程中直接注入對應 Bean 資源即可。

這只是簡單的三連環問答,不知道有多少同學能夠完整的回答出來。

其實 Spring Boot 中有很多的技術點可以挖掘,今天給大家整理了十個高頻 Spring Boot 面試題,希望可以在後期的面試中幫助到大家。

1、Spring Boot 的自動配置是如何實現的?

Spring Boot 項目的啓動註解是:@SpringBootApplication,其實它就是由下面三個註解組成的:

  • @Configuration

  • @ComponentScan

  • @EnableAutoConfiguration

其中 @EnableAutoConfiguration 是實現自動配置的入口,該註解又通過 @Import 註解導入了AutoConfigurationImportSelector,在該類中加載 META-INF/spring.factories 的配置信息。然後篩選出以 EnableAutoConfiguration 爲 key 的數據,加載到 IOC 容器中,實現自動配置功能!

2、什麼是嵌入式服務器?我們爲什麼要使用嵌入式服務器呢?

思考一下在你的虛擬機上部署應用程序需要些什麼。

第一步:安裝 Java

第二部:安裝 Web 或者是應用程序的服務器(Tomat/Wbesphere/Weblogic 等等)

第三部:部署應用程序 war 包

如果我們想簡化這些步驟,應該如何做呢?

讓我們來思考如何使服務器成爲應用程序的一部分?

你只需要一個安裝了 Java 的虛擬機,就可以直接在上面部署應用程序了,

是不是很爽?

這個想法是嵌入式服務器的起源。

當我們創建一個可以部署的應用程序的時候,我們將會把服務器(例如,tomcat)嵌入到可部署的服務器中。

例如,對於一個 Spring Boot 應用程序來說,你可以生成一個包含 Embedded Tomcat 的應用程序 jar。你就可以像運行正常 Java 應用程序一樣來運行 web 應用程序了。

嵌入式服務器就是我們的可執行單元包含服務器的二進制文件(例如,tomcat.jar)。

3、微服務同時調用多個接口,怎麼支持事務的啊?

支持分佈式事務,可以使用Spring Boot集成 Aatomikos來解決,但是我一般不建議這樣使用,因爲使用分佈式事務會增加請求的響應時間,影響系統的TPS。一般在實際工作中,會利用消息的補償機制來處理分佈式的事務。

4、shiro和oauth還有cas他們之間的關係是什麼?問下您公司權限是如何設計,還有就是這幾個概念的區別。

cas和oauth是一個解決單點登錄的組件,shiro主要是負責權限安全方面的工作,所以功能點不一致。但往往需要單點登陸和權限控制一起來使用,所以就有 cas+shiro或者oauth+shiro這樣的組合。

token一般是客戶端登錄後服務端生成的令牌,每次訪問服務端會進行校驗,一般保存到內存即可,也可以放到其他介質;redis可以做Session共享,如果前端web服務器有幾臺負載,但是需要保持用戶登錄的狀態,這場景使用比較常見。

我們公司使用oauth+shiro這樣的方式來做後臺權限的管理,oauth負責多後臺統一登錄認證,shiro負責給登錄用戶賦予不同的訪問權限。

5、各服務之間通信,對Restful和Rpc這2種方式如何做選擇?

在傳統的SOA治理中,使用rpc的居多;Spring Cloud默認使用restful進行服務之間的通訊。rpc通訊效率會比restful要高一些,但是對於大多數公司來講,這點效率影響甚微。我建議使用restful這種方式,易於在不同語言實現的服務之間通訊。

6、怎麼設計無狀態服務?

對於無狀態服務,首先說一下什麼是狀態:如果一個數據需要被多個服務共享,才能完成一筆交易,那麼這個數據被稱爲狀態。進而依賴這個“狀態”數據的服務被稱爲有狀態服務,反之稱爲無狀態服務。

那麼這個無狀態服務原則並不是說在微服務架構裏就不允許存在狀態,表達的真實意思是要把有狀態的業務服務改變爲無狀態的計算類服務,那麼狀態數據也就相應的遷移到對應的“有狀態數據服務”中。

場景說明:例如我們以前在本地內存中建立的數據緩存、Session緩存,到現在的微服務架構中就應該把這些數據遷移到分佈式緩存中存儲,讓業務服務變成一個無狀態的計算節點。遷移後,就可以做到按需動態伸縮,微服務應用在運行時動態增刪節點,就不再需要考慮緩存數據如何同步的問題。

7、Spring Cache 三種常用的緩存註解和意義?

@Cacheable ,用來聲明方法是可緩存,將結果存儲到緩存中以便後續使用相同參數調用時不需執行實際的方法,直接從緩存中取值。

@CachePut,使用 @CachePut 標註的方法在執行前,不會去檢查緩存中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中。

@CacheEvict,是用來標註在需要清除緩存元素的方法或類上的,當標記在一個類上時表示其中所有的方法的執行都會觸發緩存的清除操作。

8、Spring Boot 如何設置支持跨域請求?

現代瀏覽器出於安全的考慮, HTTP 請求時必須遵守同源策略,否則就是跨域的 HTTP 請求,默認情況下是被禁止的,IP(域名)不同、或者端口不同、協議不同(比如 HTTP、HTTPS)都會造成跨域問題。

一般前端的解決方案有:

  • ① 使用 JSONP 來支持跨域的請求,JSONP 實現跨域請求的原理簡單的說,就是動態創建<script>標籤,然後利用<script>的 SRC 不受同源策略約束來跨域獲取數據。缺點是需要後端配合輸出特定的返回信息。

  • ② 利用反應代理的機制來解決跨域的問題,前端請求的時候先將請求發送到同源地址的後端,通過後端請求轉發來避免跨域的訪問。

後來 HTML5 支持了 CORS 協議。CORS 是一個 W3C 標準,全稱是”跨域資源共享”(Cross-origin resource sharing),允許瀏覽器向跨源服務器,發出 XMLHttpRequest 請求,從而克服了 AJAX 只能同源使用的限制。它通過服務器增加一個特殊的 Header[Access-Control-Allow-Origin]來告訴客戶端跨域的限制,如果瀏覽器支持 CORS、並且判斷 Origin 通過的話,就會允許 XMLHttpRequest 發起跨域請求。

前端使用了 CORS 協議,就需要後端設置支持非同源的請求,Spring Boot 設置支持非同源的請求有兩種方式。

第一,配置 CorsFilter。


@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
          config.addAllowedOrigin("*");
          config.setAllowCredentials(true);
          config.addAllowedMethod("*");
          config.addAllowedHeader("*");
          config.addExposedHeader("*");

        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        return new CorsFilter(configSource);
    }
}

需要配置上述的一段代碼。第二種方式稍微簡單一些。

第二,在啓動類上添加:


public class Application extends WebMvcConfigurerAdapter {  

    @Override  
    public void addCorsMappings(CorsRegistry registry) {  

        registry.addMapping("/**")  
                .allowCredentials(true)  
                .allowedHeaders("*")  
                .allowedOrigins("*")  
                .allowedMethods("*");  

    }  
}  

9、JPA 和 Hibernate 有哪些區別?JPA 可以支持動態 SQL 嗎?

JPA本身是一種規範,它的本質是一種ORM規範(不是ORM框架,因爲JPA並未提供ORM實現,只是制定了規範)因爲JPA是一種規範,所以,只是提供了一些相關的接口,但是接口並不能直接使用,JPA底層需要某種JPA實現,Hibernate 是 JPA 的一個實現集。

JPA 是根據實體類的註解來創建對應的表和字段,如果需要動態創建表或者字段,需要動態構建對應的實體類,再重新調用Jpa刷新整個Entity。動態SQL,mybatis支持的最好,jpa也可以支持,但是沒有Mybatis那麼靈活。

10、Spring 、Spring Boot 和 Spring Cloud 的關係?

Spring 最初最核心的兩大核心功能 Spring Ioc 和 Spring Aop 成就了 Spring,Spring 在這兩大核心的功能上不斷的發展,纔有了 Spring 事務、Spring Mvc 等一系列偉大的產品,最終成就了 Spring 帝國,到了後期 Spring 幾乎可以解決企業開發中的所有問題。

Spring Boot 是在強大的 Spring 帝國生態基礎上面發展而來,發明 Spring Boot 不是爲了取代 Spring ,是爲了讓人們更容易的使用 Spring 。

Spring Cloud 是一系列框架的有序集合。它利用 Spring Boot 的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用 Spring Boot 的開發風格做到一鍵啓動和部署。

Spring Cloud 是爲了解決微服務架構中服務治理而提供的一系列功能的開發框架,並且 Spring Cloud 是完全基於 Spring Boot 而開發,Spring Cloud 利用 Spring Boot 特性整合了開源行業中優秀的組件,整體對外提供了一套在微服務架構中服務治理的解決方案。

用一組不太合理的包含關係來表達它們之間的關係。

Spring ioc/aop > Spring > Spring Boot > Spring Cloud


喜歡我的文章,請關注我的公衆號

Spring Boot 面試,一個問題就幹趴下了!

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