我本身總結的Java學習的系統知識點以及面試問題,已經開源,目前已經 41k+ Star。會一直完善下去,歡迎建議和指導,同時也歡迎Star: https://github.com/Snailclimb...
這篇文章主要是想經過一些問題,加深你們對於 Spring 的理解,因此不會涉及太多的代碼!這篇文章整理了挺長時間,下面的不少問題我本身在使用 Spring 的過程當中也並無注意,本身也是臨時查閱了不少資料和書籍補上的。網上也有一些不少關於 Spring 常見問題/面試題整理的文章,我感受大部分都是互相 copy,並且不少問題也不是很汗,有些回答也存在問題。因此,本身花了一週的業餘時間整理了一下,但願對你們有幫助。html
Spring 是一種輕量級開發框架,旨在提升開發人員的開發效率以及系統的可維護性。Spring 官網:https://spring.io/。前端
咱們通常說 Spring 框架指的都是 Spring Framework,它是不少模塊的集合,使用這些模塊能夠很方便地協助咱們進行開發。這些模塊是:核心容器、數據訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測試模塊。好比:Core Container 中的 Core 組件是Spring 全部組件的核心,Beans 組件和 Context 組件是實現IOC和依賴注入的基礎,AOP組件用來實現面向切面編程。java
Spring 官網列出的 Spring 的 6 個特徵:git
下圖對應的是 Spring4.x 版本。目前最新的5.x版本中 Web 模塊的 Portlet 組件已經被廢棄掉,同時增長了用於異步響應式處理的 WebFlux 組件。github
IoC(Inverse of Control:控制反轉)是一種設計思想,就是 將本來在程序中手動建立對象的控制權,交由Spring框架來管理。 IoC 在其餘語言中也有應用,並不是 Spirng 特有。 IoC 容器是 Spring 用來實現 IoC 的載體, IoC 容器實際上就是個Map(key,value),Map 中存放的是各類對象。web
將對象之間的相互依賴關係交給 IOC 容器來管理,並由 IOC 容器完成對象的注入。這樣能夠很大程度上簡化應用的開發,把應用從複雜的依賴關係中解放出來。 IOC 容器就像是一個工廠同樣,當咱們須要建立一個對象的時候,只須要配置好配置文件/註解便可,徹底不用考慮對象是如何被建立出來的。 在實際項目中一個 Service 類可能有幾百甚至上千個類做爲它的底層,假如咱們須要實例化這個 Service,你可能要每次都要搞清這個 Service 全部底層類的構造函數,這可能會把人逼瘋。若是利用 IOC 的話,你只須要配置好,而後在須要的地方引用就好了,這大大增長了項目的可維護性且下降了開發難度。面試
Spring 時代咱們通常經過 XML 文件來配置 Bean,後來開發人員以爲 XML 文件來配置不太好,因而 SpringBoot 註解配置就慢慢開始流行起來。spring
推薦閱讀:https://www.zhihu.com/questio...sql
Spring IOC的初始化過程:
數據庫
IOC源碼閱讀
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 。
Spring AOP 屬於運行時加強,而 AspectJ 是編譯時加強。 Spring AOP 基於代理(Proxying),而 AspectJ 基於字節碼操做(Bytecode Manipulation)。
Spring AOP 已經集成了 AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。AspectJ 相比於 Spring AOP 功能更增強大,可是 Spring AOP 相對來講更簡單,
若是咱們的切面比較少,那麼二者性能差別不大。可是,當切面太多的話,最好選擇 AspectJ ,它比Spring AOP 快不少。
大部分時候咱們並無在系統中使用多線程,因此不多有人會關注這個問題。單例 bean 存在線程問題,主要是由於當多個線程操做同一個對象的時候,對這個對象的非靜態成員變量的寫操做會存在線程安全問題。
常見的有兩種解決辦法:
這部分網上有不少文章都講到了,下面的內容整理自:https://yemengying.com/2016/0... 。
set()
方法設置一些屬性值。BeanNameAware
接口,調用 setBeanName()
方法,傳入Bean的名字。BeanClassLoaderAware
接口,調用 setBeanClassLoader()
方法,傳入 ClassLoader
對象的實例。BeanFactoryAware
接口,調用 setBeanClassLoader()
方法,傳入 ClassLoade
r對象的實例。*.Aware
接口,就調用相應的方法。BeanPostProcessor
對象,執行postProcessBeforeInitialization()
方法InitializingBean
接口,執行afterPropertiesSet()
方法。BeanPostProcessor
對象,執行postProcessAfterInitialization()
方法DisposableBean
接口,執行 destroy()
方法。圖示:
與之比較相似的中文版本:
談到這個問題,咱們不得不提提以前 Model1 和 Model2 這兩個沒有 Spring MVC 的時代。
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 的簡單原理圖以下:
原理以下圖所示:
上圖的一個筆誤的小問題:Spring MVC 的入口函數也就是前端控制器 DispatcherServlet
的做用是接收請求,響應結果。
流程說明(重要):
DispatcherServlet
。DispatcherServlet
根據請求信息調用 HandlerMapping
,解析請求對應的 Handler
。Handler
(也就是咱們日常說的 Controller
控制器)後,開始由 HandlerAdapter
適配器處理。HandlerAdapter
會根據 Handler
來調用真正的處理器開處理請求,並處理相應的業務邏輯。ModelAndView
對象,Model
是返回的數據對象,View
是個邏輯上的 View
。ViewResolver
會根據邏輯 View
查找實際的 View
。DispaterServlet
把返回的 Model
傳給 View
(視圖渲染)。View
返回給請求者(瀏覽器)關於下面一些設計模式的詳細介紹,能夠看筆主前段時間的原創文章《面試官:「談談Spring中都用到了那些設計模式?」。》 。
BeanFactory
、ApplicationContext
建立 bean 對象。jdbcTemplate
、hibernateTemplate
等以 Template 結尾的對數據庫操做的類,它們就使用到了模板模式。Controller
。@Component
註解做用於類,而@Bean
註解做用於方法。@Component
一般是經過類路徑掃描來自動偵測以及自動裝配到Spring容器中(咱們可使用 @ComponentScan
註解定義要掃描的路徑從中找出標識了須要裝配的類自動裝配到 Spring 的 bean 容器中)。@Bean
註解一般是咱們在標有該註解的方法中定義產生這個 bean,@Bean
告訴了Spring這是某個類的示例,當我須要用它的時候還給我。@Bean
註解比 Component
註解的自定義性更強,並且不少地方咱們只能經過 @Bean
註解來註冊bean。好比當咱們引用第三方庫中的類須要裝配到 Spring
容器時,則只能經過 @Bean
來實現。@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(); } }
咱們通常使用 @Autowired
註解自動裝配 bean,要想把類標識成可用於 @Autowired
註解自動裝配的 bean 的類,採用如下註解可實現:
@Component
:通用的註解,可標註任意類爲 Spring
組件。若是一個Bean不知道屬於拿個層,可使用@Component
註解標註。@Repository
: 對應持久層即 Dao 層,主要用於數據庫相關操做。@Service
: 對應服務層,主要涉及一些複雜的邏輯,須要用到 Dao層。@Controller
: 對應 Spring MVC 控制層,主要用戶接受用戶請求並調用 Service 層返回數據給前端頁面。聲明式事務又分爲兩種:
TransactionDefinition 接口中定義了五個表示隔離級別的常量:
支持當前事務的狀況:
不支持當前事務的狀況:
其餘狀況:
若是你們想要實時關注我更新的文章以及分享的乾貨的話,能夠關注個人公衆號。
《Java面試突擊》: 由本文檔衍生的專爲面試而生的《Java面試突擊》V2.0 PDF 版本公衆號後臺回覆 "Java面試突擊" 便可免費領取!
Java工程師必備學習資源: 一些Java工程師經常使用學習資源公衆號後臺回覆關鍵字 「1」 便可免費無套路獲取。