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