請簡述 Spring 框架的核心是什么?它主要包含了哪些核心模塊?
spring的核心模塊主要有spring-core(工具類,資源加載),spring-bean(bean的定義,創建,封裝),spring-context。這幾個模塊就形成了spring的核心概念,容器化,控制反轉,依賴注入。所謂容器化就是spring會在啟動初始化根據一些策略比如web或者webflux去生產一個子類上下文,然后在初始化的過程中,填充容器工廠,bean通過控制反轉的概率將自己定義交給容器中的bean工廠進行創建填充,然后通過依賴注入到其他需要目標bean的bean實例。
spring還提供了一個很重要的模塊spring-aop+spring-aspects,通過jdk或者cglib反射生成bean的代理對象,創建AOP鏈,不僅解決了循環依賴,還為bean功能提供了無侵入增強。
Spring Boot 的主要目標是解決什么問題?它是通過哪些核心特性來實現這一目標的?
1.配置簡易化:spring提供了yml配置,以及@SpringApplicationRun組合注解的自動配置,避免大量配置文件。
2.部署簡易化:springboot里面內嵌了一些容器,比如tomcat,不需要額外部署單獨的。
3.依賴簡易化:集成了maven或gradle工具,通過依賴樹解決依賴沖突。
4.開發簡易化:通過springboot實現的自動配置注解和鉤子函數,開發者可以通過spring.factories去實現自己的配置以及鉤子。
自定義一個spring-starter中使用@Configuration的配置類,讓其被spring掃描識別到有幾種方式
1.spring.factories中的org.springframework.boot.autoconfigure.EnableAutoConfiguration=\添加自己的配置。
2.spring新版本創建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,添加自己的配置
3.自定義@EnableYourStarter,@EnableYourStarter上添加@Import(YourAutoConfiguration.class),引入該starter的業務啟動方法添加該注解,會自動注入import的類為bean。
請描述 Spring MVC 處理一個 HTTP 請求的核心工作流程
首先瀏覽器發送一個http請求,這個時候會先到springmvc的 Dispatcherservlet, Dispatcherservlet會調用handleMapping來解析該http請求所映射的handleMethod鏈,handleMethod鏈調用適配器執行contorller,執行業務完成后,如果業務添加了@ReponseBody會返回json格式數據,如果沒有就會返回modleAndView給Dispatcherservlet,Dispatcherservlet會將其交給視圖解析器,解析完后返回給瀏覽器。
Spring Framework 中的 Bean 作用域(Scope)有哪幾種?請簡要說明它們之間的區別。
有以下幾種,單例,原型,請求,會話,應用。單例主要是bean就是以單例模式創建的,所有獲取該bean的都是一個實例。原型就是每次都新建一個bean使用,不復用。請求主要是一次請求下會有一個實例bean,在請求生命周期結束死亡。會話是一次會話有一個實例bean,會話結束bean死亡。應用主要是一個應用上下文中有一個實例bean,應用生命周期結束死亡。
在 Spring Boot 中,@SpringBootApplication 注解是一個組合注解,它主要由哪三個核心注解組成?并請簡要說明每個注解的作用。
@SpringbootConfiguration:@Configuration的別名,這個注解作用就是將該類標為配置類,保證內部@bean被容器解析。
@EnableAutoConfiguration:該注解是啟用自動配置,將spring-starter中的通過spring.factories注冊的配置條件化裝配進來。
@ComponetScan:默認掃描當前包和子包所有的@Componet注解以及其派生注解,實現業務的業務bean自動掃描注入。
Spring 框架中,什么是事務傳播行為(Transaction Propagation)?請列舉并簡要說明 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRES_NEW 這兩種常見傳播行為的區別。
事務傳播行為主要是兩個方法都有事務的情況下的調用中事務的策略,因為聲明式事務時AOP實現的,所有調用都要基于代理對象進行,如果是required,就會繼承老的事務,如果是requires_new被調用方的事務AOP會新建一個事務進行處理。特別注意的是,如果是分布式seata事務,是不推薦spring原生的事務注解的,如果需要使用也是使用required傳播級別,因為seata分布式事務也是基于AOP實現的,只是優先級比spring事務低,將其包住了,如果用了requires_new的級別,會導致新建一個事務上下文,導致事務懸掛,該事務會新建一個seata事務分支,該新事務會單獨提交,全局事務回滾的時候需要補償。
Spring MVC 中的 @RestController 注解和 @Controller 和@RequstMapping注解有什么區別?
@RestController 時@ReponseBody和@Controller的組合,直接單獨說明作用。@ReponseBody的作用是將告訴dispatherServlet跳過視圖解析器,將返回值直接序列化返回給瀏覽器,而@Controller注解默認需要走視圖解析,同時因為@Controller是@Componet的派生注解,自身也會注冊成一個bean。@RequstMapping及其派生注解主要是提供給handleMapping注冊成HandleMethod,對外暴露接口。
請解釋 Spring 框架中 Bean 的生命周期。簡要描述從創建到銷毀的過程中,有哪些重要的擴展點(例如,你可以通過哪些方式介入這個過程)。
1.首先是bean定義的創建,創建填充好定義后,觸發beanpostprocesser前置鉤子,然后進入創建流程,該流程會首先創建初始bean,判斷是否有循環依賴。
2.如果有循環依賴,需要將依賴bean的早期引用進入三級緩存,當前依賴bean注入時候創建依賴bean放入二級緩存方便當前bean注入,如果沒有循環依賴就進入bean的填充環節,填充屬性后,這里有可能是代理也有可能是原始對象。
3.屬性填充完成后,立即觸發aware函數調用將spring系統的引用拿給bean,方便bean使用容器內部東西。
4.觸發initializingbean鉤子函數進行bean處理。
5.執行beanpostprocesser后置鉤子,這里執行如果有事務注解或者AOP注解的話,需要執行AOP鏈,判斷當前是否有代理對象,如果沒有,就添加,有就復用,增強事務能力或者切面能力。
6.鉤子走完生成成品bean后,然后從三級緩存/二級緩存移除,將成品bean放入一級緩存開始使用,根據bean的作用域消亡。
請詳細解釋 Spring 是如何利用三級緩存來解決單例 Bean 的循環依賴問題的。
三級緩存存放創建bean的function,二級緩存放入早期引用,一級緩存放成品。首先將當前bean的早期引用放入三級緩存,發現有循環依賴,在三級緩存放入依賴bean的工廠function,在當前bean需要注入依賴bean的時候,從三級緩存找到依賴bean的function執行創建一個初始bean放入二級緩存,然后依賴bean進行初始化,在三級緩存找到當前bean工廠,依賴bean注入填充初始完畢從二級緩存移除到一級緩存,然后當前bean注入依賴bean,這個時候直接從一級緩存找到成品依賴bean,當前bean直接注入依賴bean并且初始化自己,就解決了循環依賴。
請詳細說明 Spring 框架中的 BeanFactory 和 ApplicationContext 的區別。以及,在現代 Spring 應用中,我們幾乎總是使用 ApplicationContext,這是為什么?
ApplicationContext來源于spring-context是IOC容器在spring的表現形式;而beanFactory來源于spring-bean,只是一個bean工廠,負責bean的管理。ApplicationContext里面包括一個beanfactory實例,實現了解耦,同時它可以拿到bean工廠完成對bean的一些前后置鉤子,以及通過aware將IOC給到bean使用。
只使用ApplicationContext的原因主要在于,ApplicationContext才是spring對外給開發者暴露的容器,其中暴露的一些接口已經可以使用ApplicationContext的bean工廠能力了,相當于采用了外觀模式,ApplicationContext有beanfactory的所有功能,并且除此之外還有額外拓展。
Spring 框架中,有哪些方式可以把一個類聲明為一個 Bean?(即 Bean 的裝配方式有哪幾種?)
@Controller,@Service,@Componet,@Bean,@Configuration,其中@Controller,@Service,@Componet這種寫在業務子文件夾里面可以被spring直接掃描,@Configuration可以搭配@Bean,讓bean被發現。以及直接使用spring.factories利用spring的鉤子注冊bean.
Spring AOP 和 AspectJ 有什么區別?Spring AOP 是基于哪種方式實現的?它在什么情況下會選擇使用 JDK 動態代理,什么情況下會選擇 CGLIB?
spring aop是基于動態代理做的切面增強。而AspectJ是使用字節碼增強的能力去增強功能,增強的jar屬于另一個服務。如果是接口代理就會選擇jdk動態代理,如果是類代理就是CGLIB代理
Spring 框架中,聲明式事務管理(@Transactional)的工作原理是什么?請詳細說明它是如何通過 AOP 和代理機制實現的,以及在什么情況下會失效。
spring的聲明式事務是基于AOP做的,他在AOP的前置切面建立事務,在AOP的后置切面提交事務。如果你不通過代理對象去調用相關服務,AOP就會失效,比如直接this或者直接調用方法,這種就會調用原始對象。還有就是不符合AOP切面生成的,比如方法聲明非public,這種就無法生成切面,事務也會失效。
Spring Framework 中如何管理多數據源的事務?在一個需要同時操作兩個不同數據庫的業務方法上,如何使用 Spring 事務保證數據一致性?請描述實現思路和需要注意的關鍵問題。
spring framework有所有數據源的事務管理器,如果需要跨數據源做事務有多種方式,1:使用編程式事務,在A,B兩個數據源都成功的時候進行提交,如果其中一個提交成功,另一個失敗,進行補償處理。2.使用seata分布式事務AT或者TCC模式控制,使用AT模式結合本地事務添加注解自動處理事務,使用TCC模式通過三段式來保障事務一致性。3.不使用事務直接控制,直接通過補償的方式寫事務表,然后補償任務。