javascript
面试中Spring常见问题
1.什么是Spring框架
Spring 是一種輕量級開發框架,旨在提高開發人員的開發效率以及系統的可維護性。
我們一般說 Spring 框架指的都是 Spring Framework,它是很多模塊的集合,使用這些模塊可以很方便地協助我們進行開發。這些模塊是:核心容器、數據訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測試模塊。比如:Core Container 中的 Core 組件是Spring 所有組件的核心,Beans 組件和 Context 組件是實現IOC和依賴注入的基礎,AOP組件用來實現面向切面編程。
Spring 官網列出的 Spring 的 6 個特征:
-
核心技術 :依賴注入(DI),AOP,事件(events),資源,i18n,驗證,數據綁定,類型轉換,SpEL。
-
測試 :模擬對象,TestContext框架,Spring MVC 測試,WebTestClient。
-
數據訪問 :事務,DAO支持,JDBC,ORM,編組XML。
-
Web支持 : Spring MVC和Spring WebFlux Web框架。
-
集成 :遠程處理,JMS,JCA,JMX,電子郵件,任務,調度,緩存。
-
語言 :Kotlin,Groovy,動態語言。
2.列舉一些重要的Spring模塊?
下圖對應的是 Spring4.x 版本。目前最新的5.x版本中 Web 模塊的 Portlet 組件已經被廢棄掉,同時增加了用于異步響應式處理的 WebFlux 組件。
- Spring Core: 基礎,可以說 Spring 其他所有的功能都需要依賴于該類庫。主要提供 IoC 依賴注入功能。
- Spring Aspects : 該模塊為與AspectJ的集成提供支持。
- Spring AOP :提供了面向切面的編程實現。
- Spring JDBC : Java數據庫連接。
- Spring JMS :Java消息服務。
- Spring ORM : 用于支持Hibernate等ORM工具。
- Spring Web : 為創建Web應用程序提供支持。
- Spring Test : 提供了對 JUnit 和 TestNG 測試的支持。
3.@RestController和@Controller
Controller 返回一個頁面
單獨使用 @Controller 不加 @ResponseBody 的話一般使用在要返回一個視圖的情況,這種情況屬于比較傳統的Spring MVC 的應用,對應于前后端不分離的情況。
@RestController 返回JSON 或 XML 形式數據
@RestController 只返回對象,對象數據直接以 JSON 或 XML 形式寫入 HTTP 響應(Response)中,這種情況屬于 RESTful Web服務,這也是目前日常開發所接觸的最常用的情況(前后端分離)。
@Controller +@ResponseBody 返回JSON 或 XML 形式數據,如果你需要在Spring4之前開發 RESTful Web服務的話,你需要使用 @Controller 并結合@ResponseBody 注解,也就是說 @Controller + @ResponseBody = @RestController (@RestController 是Spring 4 之后新加的注解)。
4.Spring IOC 和AOP
4.1談談對Spring IOC和AOP的理解
①、IoC
IoC(Inverse of Control:控制反轉)是一種設計思想,就是 將原本在程序中手動創建對象的控制權,交由Spring框架來管理。 IoC 在其他語言中也有應用,并非 Spring 特有。 IoC 容器是 Spring 用來實現 IoC 的載體, IoC 容器實際上就是個Map(key,value),Map 中存放的是各種對象。
將對象之間的相互依賴關系交給 IoC 容器來管理,并由 IoC 容器完成對象的注入。這樣可以很大程度上簡化應用的開發,把應用從復雜的依賴關系中解放出來。 IoC 容器就像是一個工廠一樣,當我們需要創建一個對象的時候,只需要配置好配置文件/注解即可,完全不用考慮對象是如何被創建出來的。 在實際項目中一個 Service 類可能有幾百甚至上千個類作為它的底層,假如我們需要實例化這個Service,你可能要每次都要搞清這個 Service 所有底層類的構造函數,這可能會把人逼瘋。如果利用IoC 的話,你只需要配置好,然后在需要的地方引用就行了,這大大增加了項目的可維護性且降低了開發難度。
Spring 時代我們一般通過 XML 文件來配置 Bean,后來開發人員覺得 XML 文件來配置不太好,于是SpringBoot 注解配置就慢慢開始流行起來。
Spring IoC的初始化過程:
②、AOP
AOP(Aspect-Oriented Programming:面向切面編程)能夠將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任(例如事務處理、日志管理、權限控制等)封裝起來,便于減少系統的重復代碼,降低模
塊間的耦合度,并有利于未來的可拓展性和可維護性。
Spring AOP就是基于動態代理的,如果要代理的對象,實現了某個接口,那么Spring AOP會使用JDK Proxy,去創建代理對象,而對于沒有實現接口的對象,就無法使用 JDK Proxy 去進行代理了,這時候Spring AOP會使用Cglib ,這時候Spring AOP會使用 Cglib 生成一個被代理對象的子類來作為代理,如下圖所示:
當然你也可以使用 AspectJ ,Spring AOP 已經集成了AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。
使用 AOP 之后我們可以把一些通用功能抽象出來,在需要用到的地方直接使用即可,這樣大大簡化了代碼量。我們需要增加新功能時也方便,這樣也提高了系統擴展性。日志功能、事務管理等等場景都用
到了 AOP 。
4.2 Spring AOP和AspectJ AOP有什么區別
Spring AOP 屬于運行時增強,而 AspectJ 是編譯時增強。 Spring AOP 基于代理(Proxying),而AspectJ 基于字節碼操作(Bytecode Manipulation)。
Spring AOP 已經集成了 AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加強大,但是 Spring AOP 相對來說更簡單,
如果我們的切面比較少,那么兩者性能差異不大。但是,當切面太多的話,最好選擇 AspectJ ,它比Spring AOP 快很多。
5.Spring bean
5.1 Spring中的bean的作用域有哪些
- singleton : 唯一 bean 實例,Spring 中的 bean 默認都是單例的。
- prototype : 每次請求都會創建一個新的 bean 實例。
- request : 每一次HTTP請求都會產生一個新的bean,該bean僅在當前HTTP request內有效。
- session : 每一次HTTP請求都會產生一個新的 bean,該bean僅在當前 HTTP session 內有效。
- global-session: 全局session作用域,僅僅在基于portlet的web應用中才有意義,Spring5已經沒有了。Portlet是能夠生成語義代碼(例如:HTML)片段的小型Java Web插件。它們基于portlet容器,可以像servlet一樣處理HTTP請求。但是,與 servlet 不同,每個 portlet 都有不同的會話
5.2Spring中的單例bean的線程安全問題
大部分時候我們并沒有在系統中使用多線程,所以很少有人會關注這個問題。單例 bean 存在線程問題,主要是因為當多個線程操作同一個對象的時候,對這個對象的非靜態成員變量的寫操作會存在線程
安全問題。
常見的有兩種解決辦法:
5.3.@Component和@Bean的區別是什么
bean 容器中)。 @Bean 注解通常是我們在標有該注解的方法中定義產生這個 bean, @Bean 告訴了Spring這是某個類的示例,當我需要用它的時候還給我。
@Bean 注解使用示例:
@Configuration public class AppConfig {@Bean public TransferService transferService() { return new TransferServiceImpl();} }上面的代碼相當于下面的xml配置
<beans><bean id="transferService" class="com.acme.TransferServiceImpl"/></beans>下面這個例子是通過 @Component 無法實現的。
@Bean public OneService getService(status) { case (status) {when 1: return new serviceImpl1();when 2:return new serviceImpl2();when 3: return new serviceImpl3();} }5.4.將一個類聲明為Spring的bean的注解有哪些
我們一般使用 @Autowired 注解自動裝配 bean,要想把類標識成可用于 @Autowired 注解自動裝配的 bean 的類,采用以下注解可實現:
- @Component :通用的注解,可標注任意類為 Spring 組件。如果一個Bean不知道屬于哪個層,可以使用 @Component 注解標注。
- @Repository : 對應持久層即 Dao 層,主要用于數據庫相關操作。
- @Service : 對應服務層,主要涉及一些復雜的邏輯,需要用到 Dao層。
- @Controller : 對應 Spring MVC 控制層,主要用戶接受用戶請求并調用 Service 層返回數據給前端頁面。
5. 5.Spring中的bean的生命周期
- Bean 容器找到配置文件中 Spring Bean 的定義。
- Bean 容器利用 Java Reflection API 創建一個Bean的實例。
- 如果涉及到一些屬性值 利用 set() 方法設置一些屬性值。
- 如果 Bean 實現了 BeanNameAware 接口,調用 setBeanName() 方法,傳入Bean的名字。
- 如果 Bean 實現了 BeanClassLoaderAware 接口,調用setBeanClassLoader() 方法,傳入ClassLoader 對象的實例。
- 與上面的類似,如果實現了其他 *.Aware 接口,就調用相應的方法。
- 如果有和加載這個 Bean 的 Spring 容器相關的 BeanPostProcessor 對象,執行
postProcessBeforeInitialization() 方法 - 如果Bean實現了 InitializingBean 接口,執行 afterPropertiesSet() 方法。
- 如果 Bean 在配置文件中的定義包含 init-method 屬性,執行指定的方法。
- 如果有和加載這個 Bean的 Spring 容器相關的 BeanPostProcessor 對象,執行postProcessAfterInitialization() 方法
- 當要銷毀 Bean 的時候,如果 Bean 實現了 DisposableBean 接口,執行 destroy() 方法。
- 當要銷毀 Bean 的時候,如果 Bean 在配置文件中的定義包含 destroy-method 屬性,執行指定的方法。
圖示:
與之比較類似的中文版本:
6.Spring MVC
6.1對于Spring MVC的理解
談到這個問題,我們不得不提提之前 Model1 和 Model2 這兩個沒有 Spring MVC 的時代。
- Model1 時代 : 很多學 Java 后端比較晚的朋友可能并沒有接觸過 Model1 模式下的 JavaWeb 應用開發。在 Model1 模式下,整個 Web 應用幾乎全部用 JSP 頁面組成,只用少量的 JavaBean 來處理數據庫連接、訪問等操作。這個模式下 JSP 即是控制層又是表現層。顯而易見,這種模式存在很多問題。比如①將控制邏輯和表現邏輯混雜在一起,導致代碼重用率極低;②前端和后端相互依賴,難以進行測試并且開發效率極低;
- Model2 時代 :學過 Servlet 并做過相關 Demo 的朋友應該了解“Java Bean(Model)+JSP(View,)+Servlet(Controller) ”這種開發模式,這就是早期的 JavaWeb MVC 開發模式。Model:系統涉及的數據,也就是 dao 和 bean。View:展示模型中的數據,只是用來展示。Controller:處理用戶請求都發送給 ,返回數據給 JSP 并展示給用戶。
Model2 模式下還存在很多問題,Model2的抽象和封裝程度還遠遠不夠,使用Model2進行開發時不可避免地會重復造輪子,這就大大降低了程序的可維護性和復用性。于是很多JavaWeb開發相關的 MVC框架應運而生比如Struts2,但是 Struts2 比較笨重。隨著 Spring 輕量級開發框架的流行,Spring 生態圈出現了 Spring MVC 框架, Spring MVC 是當前最優秀的 MVC 框架。相比于 Struts2 , Spring MVC使用更加簡單和方便,開發效率更高,并且 Spring MVC 運行速度更快。
MVC 是一種設計模式,Spring MVC 是一款很優秀的 MVC 框架。Spring MVC 可以幫助我們進行更簡潔的Web層的開發,并且它天生與 Spring 框架集成。Spring MVC 下我們一般把后端項目分為 Service層(處理業務)、Dao層(數據庫操作)、Entity層(實體類)、Controller層(控制層,返回數據給前臺頁面)。
Spring MVC 的簡單原理圖如下:
6.2Spring MVC的工作原理
Spring MVC 的入口函數也就是前端控制器 DispatcherServlet 的作用是接收請求,響應結果。
流程說明(重要):
7.Spring框架中用到了那些設計模式
- 工廠設計模式 : Spring使用工廠模式通過 BeanFactory 、 ApplicationContext 創建 bean 對象。
- 代理設計模式 : Spring AOP 功能的實現。
- 單例設計模式 : Spring 中的 Bean 默認都是單例的。
- 模板方法模式 : Spring 中 jdbcTemplate 、 hibernateTemplate 等以 Template 結尾的對數據庫操作的類,它們就使用到了模板模式。
- 包裝器設計模式 : 我們的項目需要連接多個數據庫,而且不同的客戶在每次訪問中根據需要會去訪問不同的數據庫。這種模式讓我們可以根據客戶的需求能夠動態切換不同的數據源。
- 觀察者模式: Spring 事件驅動模型就是觀察者模式很經典的一個應用。
- 適配器模式 :Spring AOP 的增強或通知(Advice)使用到了適配器模式、spring MVC 中也是用到了適配器模式適配 Controller 。
- …
總結
以上是生活随笔為你收集整理的面试中Spring常见问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 详解@EnableEurekaServe
- 下一篇: Spring常见注解