Spring 隨便問,我來答!
你好,我是yes。
話不多少,發(fā)車!
說下 Spring Bean 的生命周期
在說具體的生命周期前,我們需要先知曉之所以 Bean 容易被添加一些屬性,或者能在運(yùn)行時(shí)被改造就是因?yàn)樵谏? Bean 的時(shí)候,Spring對(duì)外暴露出很多擴(kuò)展點(diǎn)。
基于這些點(diǎn)我們可以設(shè)置一些邏輯,Spring 會(huì)在 Bean 創(chuàng)建的某些階段根據(jù)這些擴(kuò)展點(diǎn),基于此進(jìn)行 Bean 的改造。
有了上面的認(rèn)識(shí),我們?cè)賮砜?Spring Bean 的生命周期,我用一幅圖先總結(jié)一下:
大致了解生命周期之后,我們?cè)賮砜丛敿?xì)的操作,可以看到有好多擴(kuò)展點(diǎn)可以搞事情:
注意細(xì)節(jié),這幅圖的顏色和上面那副有對(duì)應(yīng)關(guān)系的。
我再用文字描述一下:
- 實(shí)例化Bean。
- 根據(jù)屬性,注入需要的 Bean。
- 如果 Bean 實(shí)現(xiàn)了 BeanNameAware 等 aware 接口,則執(zhí)行 aware 注入。
- 如果有 BeanPostProcessor,則執(zhí)行BeanPostProcessor#postProcessBeforeInitialization 方法。
- 如果 Bean 是 InitializingBean,則執(zhí)行 afterPropertiesSet 方法。
- 如果有 initMethod ,則執(zhí)行。
- 如果有 BeanPostProcessor,執(zhí)行BeanPostProcessor#postProcessAfterInitialization 方法。
- 使用 Bean。
- 如果 Bean 是 DisposableBean,則執(zhí)行 destroy 方法。
- 如果有 destroy 方法,則執(zhí)行。
說下對(duì) Spring MVC 的理解?
Spring MVC 是基于 Servlet API 構(gòu)建的,可以說核心就是 DispatcherServlet,即一個(gè)前端控制器。
還有幾個(gè)重要的組件:處理器映射、控制器、視圖解析器等。
由這幾個(gè)組件讓我們與 Servlet 解耦,不需要寫一個(gè)個(gè) Servlet ,基于 Spring 的管理就可以很好的實(shí)現(xiàn) web 應(yīng)用,簡(jiǎn)單,方便。
然后關(guān)于 MVC 的解釋,我就不提了,什么 Model,View,Controller 啥的。
Spring MVC 具體的工作原理?
當(dāng)一個(gè)請(qǐng)求過來的時(shí)候,由 DispatcherServlet 接待,它會(huì)根據(jù)處理器映射(HandlerMapping)找到對(duì)應(yīng)的 HandlerExecutionChain(這里面包含了很多定義的 HandlerInterceptor,攔截器)。
然后通過 HandlerAdapter 適配器的適配(適配器模式了解一下)后,執(zhí)行 handler,即通過 controller 的調(diào)用,返回 ModelAndView。
然后 DispatcherServlet 解析得到 ViewName,將其傳給 ViewResoler 視圖解析器,解析后獲得 View 視圖。
然后 DispatcherServlet 將 model 數(shù)據(jù)填充到 view ,得到最終的 Responose 返回給用戶。
我們常用的視圖有 jsp、freemaker、velocity 等。
SpringMVC 父子容器是什么知道嗎?
官網(wǎng)上有幅圖可以了解下:
可以看到,services 和 repositories 是屬于父容器的,而 Controllers 等是屬于子容器的。
那為什么會(huì)有父子之分?
其實(shí) Spring 容器在啟動(dòng)的時(shí)候,不會(huì)有 SpringMVC 這個(gè)概念,只會(huì)掃描文件然后創(chuàng)建一個(gè) context ,此時(shí)就是父容器。
然后發(fā)現(xiàn)是 web 服務(wù)需要生成 DispatcherServlet ,此時(shí)就會(huì)調(diào)用 DispatcherServlet#init,這個(gè)方法里面最會(huì)生成一個(gè)新的 context,并把之前的 context 置為自己的 Parent。
這樣就有了父子之分,這樣指責(zé)就更加清晰,子容器就負(fù)責(zé) web 部分,父容器則是通用的一些 bean。
也正是有了父子之分,如果有些人沒把 controller 掃包的配置寫在 spring-servlet.xml ,而寫到了 service.xml 里,那就會(huì)把 controller 添加到父容器里,這樣子容器里面就找不到了,請(qǐng)求就 404 了。
當(dāng)然,如果你把 services 和 repositories 添加到子容器是沒影響的,不過沒必要,分層還是比較好的方式。
對(duì)了,子容器可以用父容器的 Bean,父容器不能用子容器的 Bean。
你了解的 Spring 都用到哪些設(shè)計(jì)模式
工廠模式,從名字就看出來了 BeanFacotry。
模板方法,什么 JdbcTemplate、RestTemplate 。
代理模式,AOP 整的都是代理。
單例,這都不需要說了。
責(zé)任鏈模式,比如攔截器。
觀察者模式,Spring里的監(jiān)聽器。
適配器模式...SpringMVC 提到的 handlerApdaper。
太多啦...
Spring 事務(wù)有幾個(gè)隔離級(jí)別
從源碼定義我們可以看到,一共有 5 種隔離級(jí)別,而 DEFAULT 就是使用數(shù)據(jù)庫(kù)定義的隔離級(jí)別。
其他幾種分別是:讀未提交、讀已提交、可重復(fù)讀、序列化。
具體幾個(gè)隔離級(jí)別的概念我就不介紹了,應(yīng)該都很清楚。
不清楚的看我這篇 MySQL 的文章:mysql總結(jié)。
文章的后半段有寫。
Spring 有哪幾種事務(wù)傳播行為?
從源碼來看,一共有 7 種事務(wù)傳播行為:
- PROPAGATION_REQUIRED(默認(rèn)) 如果當(dāng)前存在事務(wù),則用當(dāng)前事務(wù),如果沒有事務(wù)則新起一個(gè)事務(wù)。
- PROPAGATION_SUPPORTS 支持當(dāng)前事務(wù),如果不存在,則以非事務(wù)方式執(zhí)行。
- PROPAGATION_MANDATORY 支持當(dāng)前事務(wù),如果不存在,則拋出異常。
- PROPAGATION_REQUIRES_NEW 創(chuàng)建一個(gè)新事務(wù),如果存在當(dāng)前事務(wù),則掛起當(dāng)前事務(wù)。
- PROPAGATION_NOT_SUPPORTED 不支持當(dāng)前事務(wù),始終以非事務(wù)方式執(zhí)行。
- PROPAGATION_NEVER 不支持當(dāng)前事務(wù),如果當(dāng)前存在事務(wù),則拋出異常。
- PROPAGATION_NESTED 如果當(dāng)前事務(wù)存在,則在嵌套事務(wù)中執(zhí)行,內(nèi)層事務(wù)依賴外層事務(wù),如果外層失敗,則會(huì)回滾內(nèi)層,內(nèi)層失敗不影響外層。
Spring 事務(wù)傳播行為有什么用?這題是群里有位小伙伴遇到的面試題。
其實(shí)答案就幾個(gè)字:控制事務(wù)的邊界。