Spring四、Spring IOC、DI、MVC、AOP時序圖


 最近一直在研究Spring IOC、DI、AOP、MVC幾個步驟的源碼,畫出幾種的時序圖,方便以后查看回憶源碼

1、IOC容器初始化

 IOC 容器的初始化包含了BeanDefinition資源文件Resource定位、解析加載和注冊三個步驟。
 步驟依次為 : 讀取資源文件為InputStream --> 轉為Resource -> Document -> 解析元素節點封裝為 BeanDefinition
-> 放入IOC容器中,即DefaultListableBeanFactory的 Map<String, BeanDefinition> beanDefinitionMap

  主要的幾個類
  BeanFactory : BeanFactory及其子類也就是我們說的IOC容器,Spring提供了多種IOC容器以供選擇
      ListableBeanFactory接口表示Bean可列表化、HierarchicalBeanFactory接口表示Bean有繼承關系、AutowireCapableBeanFactory定義自動裝配;
      以上三個接口的默認實現均為 org.springframework.beans.factory.support.DefaultListableBeanFactory
  BeanDefinition : 描述Bean在資源文件中的配置信息及相互關系
  BeanDefinitionReader : 解析資源為BeanDefinition 

1.1 基於xml的Ioc容器初始化

入口:

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IoCTest {

    public static void main(String[] args) {
        //  
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        applicationContext.getBean("myUser");
        
    }
    
}

IOC實現流程及原理
Spring IOC時序圖

1.2 基於web的Ioc容器初始化

入口: web Ioc容器初始化由DispatcherServlet.init()方法開始

  DispatcherServlet.init() 其實是調用的父類 org.springframework.web.servlet.HttpServletBean#init方法,之后 
    -> org.springframework.web.servlet.FrameworkServlet#initServletBean 
      -> org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext
        -> org.springframework.web.servlet.FrameworkServlet#configureAndRefreshWebApplicationContext
          -> org.springframework.context.support.AbstractApplicationContext#refresh
            -> org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
   到此,余下 web Ioc容器的初始化步驟和 XML IOC容器的初始化都經由 AbstractApplicationContext#obtainFreshBeanFactory 來完成,和上面時序圖一樣。

1.3 基於注解的Ioc容器初始化

component-scan 掃描指定包路徑,解析class頭的注解,及注解名稱,封裝為BeanDefinition;之后反射獲取屬性及value,封裝為PropertyValue,賦值給BeanDefinition,最后放入Spring IOC容器中。

2、DI依賴注入時序圖

  入口: org.springframework.context.support.ClassPathXmlApplicationContext#getBean(java.lang.String)  
        ->  org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String)
  
  實現原理: 反射為屬性賦值,如果存在循環依賴,使用三級緩存來處理:
      一級緩存: 類成功實例化,屬性也成功賦值
      二級緩存: 類成功實例化,屬性存在循環依賴、不能賦值 
      三級緩存: 類不能成功實例化 (指定使用構造器方法進行實例化,構造器中的參數存在循環引用) 
    在初始化完畢,會先遍歷三級緩存進行依賴注入,放入一級緩存;然后遍歷二級緩存,放入一級緩存; 

3、AOP時序圖

  入口: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
  
  實現邏輯: 
    基於JDK或者Cglib的動態代理通過字節碼重組實現;
    首先加載配置的切面PointCut及方法攔截通知Advice的配置,在進行依賴注入時,為每個類及類的每個方法正則匹配是否符合切面表達式,符合的話判斷該類是否實現了接口,實現接口的話使用JDK的動態代理,否則使用Cglib的動態代理字節碼重組重新織入通知代碼,以次生產新的代理類。    

  AdvisedSupport -> AopConfig -> Advice -> JDKProxy or CglibProxy

4、MVC流程時序圖

  入口: DispatcherServlet.init()  &&   DispatcherServlet.doService()

  實現邏輯:
  首先程序啟動初始化Spring九大組件:
    初始化url映射HandlerMapping; 掃描Controller下的所有RequestMapping,組成正則類型的url Pattern,並與Controller、method綁定關系組成HandlerMapping對象;
    初始化參數適配器HandlerAdapter;記錄RequestMapping對應method的參數類型,參數名稱,RequestParam綁定名稱等
    初始化視圖解析器ViewResolver;
    .... 
  之后再頁面url發出請求后,根據請求url正則匹配到對應1到多個HandlerMapping,然后找出對應的參數適配器HandlerAdapter,反射進行方法調用返回ModelAndView,再由ViewResolver進行解析、占位符替換,最后對View渲染,將html或jsp通過Response返回   

  DispatcherServlet -> HandlerMapping -> HandlerAdapter -> ModelAndView -> ViewResolver -> View  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM