+圖片講解))
1、Spring框架中的單例bean是線程安全的嗎候選人不是線程安全的。當(dāng)多用戶同時(shí)請(qǐng)求一個(gè)服務(wù)時(shí)容器會(huì)給每個(gè)請(qǐng)求分配一個(gè)線程這些線程會(huì)并發(fā)執(zhí)行業(yè)務(wù)邏輯。如果處理邏輯中包含對(duì)單例狀態(tài)的修改比如修改單例的成員屬性就必須考慮線程同步問題。Spring框架本身并不對(duì)單例bean進(jìn)行線程安全封裝線程安全和并發(fā)問題需要開發(fā)者自行處理。通常在項(xiàng)目中使用的Spring bean是不可變狀態(tài)如Service類和DAO類因此在某種程度上可以說Spring的單例bean是線程安全的。如果bean有多種狀態(tài)如ViewModel對(duì)象就需要自行保證線程安全。最簡(jiǎn)單的解決辦法是將單例bean的作用域由“singleton”變更為“prototype”。import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; Service Scope(prototype) // 指定多例作用域 public class UserService { }2、什么是AOP候選人AOP即面向切面編程在Spring中用于將那些與業(yè)務(wù)無關(guān)但對(duì)多個(gè)對(duì)象產(chǎn)生影響的公共行為和邏輯抽取出來實(shí)現(xiàn)公共模塊復(fù)用降低耦合。常見的應(yīng)用場(chǎng)景包括公共日志保存和事務(wù)處理。3、你們項(xiàng)目中有沒有使用到AOP我們之前在后臺(tái)管理系統(tǒng)中使用AOP來記錄系統(tǒng)操作日志。主要思路是使用AOP的環(huán)繞通知和切點(diǎn)表達(dá)式找到需要記錄日志的方法然后通過環(huán)繞通知的參數(shù)獲取請(qǐng)求方法的參數(shù)例如類信息、方法信息、注解、請(qǐng)求方式等并將這些參數(shù)保存到數(shù)據(jù)庫(kù)。4、Spring中的事務(wù)是如何實(shí)現(xiàn)的候選人Spring實(shí)現(xiàn)事務(wù)的本質(zhì)是利用AOP完成的。它對(duì)方法前后進(jìn)行攔截在執(zhí)行方法前開啟事務(wù)在執(zhí)行完目標(biāo)方法后根據(jù)執(zhí)行情況提交或回滾事務(wù)。5、Spring中事務(wù)失效的場(chǎng)景有哪些在項(xiàng)目中我遇到過幾種導(dǎo)致事務(wù)失效的場(chǎng)景如果方法內(nèi)部捕獲并處理了異常沒有將異常拋出會(huì)導(dǎo)致事務(wù)失效。因此處理異常后應(yīng)該確保異常能夠被拋出。如果方法拋出檢查型異常checked exception并且沒有在Transactional注解上配置rollbackFor屬性為Exception那么異常發(fā)生時(shí)事務(wù)可能不會(huì)回滾。如果事務(wù)注解的方法不是公開public修飾的也可能導(dǎo)致事務(wù)失效。Spring 事務(wù)是AOP 動(dòng)態(tài)代理實(shí)現(xiàn)的而Spring AOPJDK 代理 / CGLIB 代理只能攔截 public 方法6、Spring的bean的生命周期候選人Spring中bean的生命周期包括以下步驟通過BeanDefinition獲取bean的定義信息。加載 xml / 注解配置解析得到BeanDefinitionBean 元信息類名、屬性、scope 等調(diào)用構(gòu)造函數(shù)實(shí)例化bean。根據(jù) BeanDefinition通過反射調(diào)用構(gòu)造方法new 出 Bean 原始對(duì)象此時(shí)對(duì)象已經(jīng)存在但屬性還沒賦值。進(jìn)行bean的依賴注入例如通過setter方法或Autowired注解。給對(duì)象屬性賦值。此時(shí) Bean 對(duì)象有屬性了但還沒有初始化。處理實(shí)現(xiàn)了Aware接口的bean。執(zhí)行aware里面重寫的方法執(zhí)行BeanPostProcessor的前置處理器。調(diào)用初始化方法如實(shí)現(xiàn)了InitializingBean接口或自定義的init-method。執(zhí)行BeanPostProcessor的后置處理器可能在這里產(chǎn)生代理對(duì)象。AOP 代理通常就是在這里生成的。之后 Bean 就可以正常使用了單例 Bean 會(huì)放入單例池。最后是銷毀bean。7、Spring中的循環(huán)引用候選人循環(huán)依賴發(fā)生在兩個(gè)或兩個(gè)以上的bean互相持有對(duì)方形成閉環(huán)。Spring框架允許循環(huán)依賴存在并通過三級(jí)緩存解決大部分循環(huán)依賴問題一級(jí)緩存單例池緩存已完成初始化的bean對(duì)象。二級(jí)緩存緩存尚未完成生命周期的早期bean對(duì)象。三級(jí)緩存緩存ObjectFactory用于創(chuàng)建bean對(duì)象和bean的代理對(duì)象。只用二級(jí)緩存在普通無 AOP 場(chǎng)景下可以解決循環(huán)依賴但是一旦 bean 需要 AOP 代理二級(jí)緩存就會(huì)出現(xiàn)問題。所以 Spring 引入第三級(jí)緩存專門處理【需要 AOP 代理】的循環(huán)依賴場(chǎng)景。那具體解決流程清楚嗎候選人解決循環(huán)依賴的流程如下實(shí)例化A對(duì)象并創(chuàng)建ObjectFactory存入三級(jí)緩存。A在初始化時(shí)需要B對(duì)象開始B的創(chuàng)建邏輯。B實(shí)例化完成也創(chuàng)建ObjectFactory存入三級(jí)緩存。B需要注入A通過三級(jí)緩存獲取ObjectFactory生成A對(duì)象存入二級(jí)緩存。B通過二級(jí)緩存獲得A對(duì)象后B創(chuàng)建成功存入一級(jí)緩存。A對(duì)象初始化時(shí)由于B已創(chuàng)建完成可以直接注入BA創(chuàng)建成功存入一級(jí)緩存。清除二級(jí)緩存中的臨時(shí)對(duì)象A。8、構(gòu)造方法出現(xiàn)了循環(huán)依賴怎么解決候選人由于構(gòu)造函數(shù)是bean生命周期中最先執(zhí)行的Spring框架無法解決構(gòu)造方法的循環(huán)依賴問題??梢允褂肔azy懶加載注解延遲bean的創(chuàng)建直到實(shí)際需要時(shí)。9、SpringMVC的執(zhí)行流程候選人SpringMVC的執(zhí)行流程包括以下步驟用戶發(fā)送請(qǐng)求到前端控制器DispatcherServlet。DispatcherServlet調(diào)用HandlerMapping找到具體處理器。HandlerMapping返回處理器對(duì)象及攔截器如果有給DispatcherServlet。DispatcherServlet調(diào)用HandlerAdapter。HandlerAdapter適配并調(diào)用具體處理器Controller。Controller執(zhí)行并返回ModelAndView對(duì)象。HandlerAdapter將ModelAndView返回給DispatcherServlet。DispatcherServlet傳給ViewResolver進(jìn)行視圖解析。ViewResolver返回具體視圖給DispatcherServlet。DispatcherServlet渲染視圖并響應(yīng)用戶。10、Springboot自動(dòng)配置原理候選人Spring Boot的自動(dòng)配置原理基于SpringBootApplication注解它封裝了SpringBootConfiguration、EnableAutoConfiguration和ComponentScan。EnableAutoConfiguration是核心它通過Import導(dǎo)入配置選擇器讀取META-INF/spring.factories文件中的類名根據(jù)條件注解決定是否將配置類中的Bean導(dǎo)入到Spring容器中。11、Spring 的常見注解有哪些候選人Spring的常見注解包括聲明Bean的注解Component、Service、Repository、Controller。依賴注入相關(guān)注解Autowired、Qualifier、Resource。設(shè)置作用域的注解Scope。配置相關(guān)注解Configuration、ComponentScan、Bean。AOP相關(guān)注解Aspect、Before、After、Around、Pointcut。12、SpringMVC常見的注解有哪些候選人SpringMVC的常見注解有RequestMapping映射請(qǐng)求路徑。RequestBody接收HTTP請(qǐng)求的JSON數(shù)據(jù)。RequestParam指定請(qǐng)求參數(shù)名稱。PathVariable從請(qǐng)求路徑中獲取參數(shù)。ResponseBody將Controller方法返回的對(duì)象轉(zhuǎn)化為JSON。RequestHeader獲取請(qǐng)求頭數(shù)據(jù)。PostMapping、GetMapping等。13、Springboot常見注解有哪些候選人Spring Boot的常見注解包括SpringBootApplication由SpringBootConfiguration、EnableAutoConfiguration和ComponentScan組成。其他注解如RestController、GetMapping、PostMapping等用于簡(jiǎn)化Spring MVC的配置。14、MyBatis執(zhí)行流程候選人MyBatis的執(zhí)行流程如下讀取MyBatis配置文件mybatis-config.xml。構(gòu)造會(huì)話工廠SqlSessionFactory。會(huì)話工廠創(chuàng)建SqlSession對(duì)象。操作數(shù)據(jù)庫(kù)的接口Executor執(zhí)行器。Executor執(zhí)行方法中的MappedStatement參數(shù)。輸入?yún)?shù)映射。輸出結(jié)果映射。15、Mybatis是否支持延遲加載候選人MyBatis支持延遲加載即在需要用到數(shù)據(jù)時(shí)才加載??梢酝ㄟ^配置文件中的lazyLoadingEnabled配置啟用或禁用延遲加載。16、延遲加載的底層原理知道嗎候選人延遲加載的底層原理主要使用CGLIB動(dòng)態(tài)代理實(shí)現(xiàn)使用CGLIB創(chuàng)建目標(biāo)對(duì)象的代理對(duì)象。調(diào)用目標(biāo)方法時(shí)如果發(fā)現(xiàn)是null值則執(zhí)行SQL查詢。獲取數(shù)據(jù)后設(shè)置屬性值并繼續(xù)查詢目標(biāo)方法。17、Mybatis的一級(jí)、二級(jí)緩存用過嗎候選人MyBatis的一級(jí)緩存是基于HashMap本地緩存作用域?yàn)閟qlSession默認(rèn)開啟。二級(jí)緩存需要單獨(dú)開啟作用域?yàn)镹amespace或mapper默認(rèn)也是采用HashMap存儲(chǔ)。18、Mybatis的二級(jí)緩存什么時(shí)候會(huì)清理緩存中的數(shù)據(jù)候選人當(dāng)作用域一級(jí)緩存Session/二級(jí)緩存Namespaces進(jìn)行了新增、修改、刪除操作后默認(rèn)該作用域下所有select中的緩存將被清空。