一、Spring框架中的單例Bean是線程安全的嗎?
【默認單例的情況下】Spring Bean并沒有可變的狀態(如Service類和DAO類),即只能查不能改,所以沒有并發問題,所以某種程度上來說Spring的單例Bean是線程安全的。
回答
Spring框架中有一個@Scope注解,默認為單例。因此當Spring的Bean中都是注入無狀態的對象,沒有線程安全問題,但如果在Bean中定義了可修改的成員變量如上述的count變量,從JVM角度看它本身屬于方法區,即線程共享的區域中,將來多個請求發來,多個線程是共享的,所以存在問題。
當然如果注冊為Bean的字段本身也是可變的【除了Service、DAO等其他的】,也存在線程安全問題,因為Bean默認為單例的,我們可以將其改為多例或者加同步鎖。
只要成員變量是不可修改的,則這個Bean是線程安全的,如果成員變量是可修改的,則可能有線程安全問題。
二、SpringMVC的執行流程
前后端分離架構:【接口開發、異步】
請求到DisPatcherServlet,還有一個過程,首先由tomcat的連接器監聽到請求,處理參數給容器,通過映射一級級找到dispatcherServlet
用戶發送的請求統一由前端控制器(DispatcherServlet統一攔截),交給處理器映射器
【負責將請求映射到對應的處理器(Controller方法),存放在一個map中】
找到了之后將方法名和handler封裝為處理器執行鏈給前端控制器
前端控制器知道了這個請求的方法,直接將請求交給處理器適配器【作用是解析參數,因為每個請求,參數類型不一樣,有基基本類型、引用類型、路徑參數等等…】,處理器適配器處理好了參數之后,再將請求發給處理器Handler【一般對應的controller都有@ResponseBody注解,即將返回結果轉換為JSON并響應】
處理器執行鏈包括了哪些東西?
- 處理器對象:即具體的 Controller 類中的處理器方法。
- 處理器攔截器(Handler Interceptor):處理器攔截器可以在處理器方法執行前、執行后,或之前和之后執行一些共同的邏輯,比如權限驗證、日志記錄等。
- 處理器方法:即處理請求的具體方法。
當請求到達前端控制器(DispatcherServlet)后,前端控制器會通過處理器映射器找到對應的處理器,并返回一個處理器執行鏈,包括了以上所述的元素。處理器執行鏈將負責依次執行處理器攔截器的前置處理、處理器方法的執行以及處理器攔截器的后置處理。
處理器攔截器的作用:
處理器攔截器與處理器執行鏈密切相關,處理器執行鏈中的處理器攔截器可以在請求進入處理器方法之前和處理器方法執行之后實施攔截邏輯。通過處理器攔截器,我們可以實現一些通用的邏輯,而不需要在每個處理器方法中重復編寫。
處理器執行鏈中包含了處理器對象和處理器方法【包含了具體的執行邏輯】,那為什么還要最終交給處理器Handler來執行處理器方法?
處理器適配器的作用是將處理器對象(Controller)轉換為處理器(Handler)的形式,然后執行其中的方法以處理請求。處理器適配器知道如何調用不同類型的處理器對象,并處理返回值以生成最終的響應給前端控制器。
因此,雖然處理器執行鏈中包含了處理器方法,但最終還需要通過調用處理器對象和處理器適配器來執行具體的處理器方法,從而完成請求的處理過程。