spring源碼解讀

一、IOC(控制反轉)、AOP(切面)、DI (依賴注入)是spring的核心部分html

    Spring是一種設計思想的體現,發生了「主從換位」的變化。應用程序由主動的建立對象,轉換稱了從IOC容器裏獲取對象,對象的建立、解析和註冊都由Spring來替用戶實現,用戶只管定義。spring

二、IoC容器的設計與實現--Bean組件與Context組件app

使用Spring時,它首先替咱們完成的時IOC容器的初始化,初始化的過程包括定義(BeanDefinition)、載入定義(loadBeanDefinitions,包含了解析的方法)、註冊定義(registerBeanDefinitions),註冊最後落實到代碼中就是框架

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

this.beanDefinitionMap.put(beanName, beanDefinition);

註冊到map集合中, 將BeanName做爲鍵, BeanDefinition做爲值保存。接下來看具體的源碼,加深IOC容器初始化的過程理解ui

2.1Bean組件this

bean組件在Spring的org.springframework.beans包下。IOC容器的初始化就在這個包裏完成的,定義、載入、註冊,對於使用者來講只要完成bean的定義就能夠了,其餘兩個由 Spring 在內部幫咱們完成了,對咱們來講是透明的。spa

bean的定義咱們很少說,能夠用配置文件定義bean,也能夠用註解的方式,接下來咱們看下Spring的作了那些操做:.net

2.1.2 BeanFactory概述設計

BeanFactory是Spring bean容器的根接口.提供獲取bean,是否包含bean,是否單例與原型,獲取bean類型,bean 別名的方法 。3d

2.1.3BeanFactory的繼承關係

咱們能夠看到DefaultListableBeanFactory  是最終的實現類,它實現了全部的接口,它也是Spring框架裏核心的類之一

2.1.4BeanDefinition概述

BeanDefinition是一個接口類,Bean 的定義主要由 BeanDefinition 實現,項目啓動首先是讀取bean的xml配置文件,而後解析xml文件中的各類bean的定義,將xml文件中的每個<bean />元素分別轉換解析成一個BeanDefinition對象,其中保存了從配置文件中讀取到的該bean的各類信息,之後全部的操做都是對這個對象的操做。

2.1.5 BeanDefinitionReader概述

BeanDefinitionReader一樣也是接口類,讀取xml配置文件,解析爲BeanDefinition對象過程是繁瑣的,整個解析過程主要經過下圖中的類完成:

2.1.6BeanDefinitionHolder概述

BeanDefinitionHolder是一個class實現類,BeanDefinitionHolder對象中持有的BeanDefinition實例的引用,還有beanName,還有bean的別名

先對這幾個類有個大致的瞭解,接下來從源碼中看它們實際的做用。

2.1.7Bean Definition從加載、解析、處理、註冊到BeanFactory的過程,也就是IOC容器的初始化過程

  1. Bean Definition加載
    用配置文件的方式定義bean ,首先要作的就是讀取xml文件
    在XmlBeanDefinitionReader類中
    &1.loadBeanDefinitions方法從xml文件中加載beanDefinition,將Resource轉化爲EncodedResource對象,交給它的重載方法來作加載前的準備,實際去加載xml文件的是方法doLoadBeanDefinitions(InputSource inputSource, Resource resource),
    
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException{
    ....
      return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    ....
    }
    &2.doLoadBeanDefinitions方法中加載獲得一個Document對象,把Document和resource交給registerBeanDefinitions完成註冊
    
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){
    ....
      Document doc = doLoadDocument(inputSource, resource);
      return registerBeanDefinitions(doc, resource);
    ....
    }
    &3.registerBeanDefinitions(Document doc, Resource resource)方法,這裏其實是建立了一個BeanDefinitionDocumentReader對象而後讓它來完成。
    public static  void main(String[] args){//直接使用BeanFactory 做爲容器
          String xmlPath = "applicationContext.xml";
          BeanFactory factory = new XmlBeanFactory(new ClassPathResource(xmlPath));
          userService = (UserService) factory.getBean("userService");
          userService.add();
    }
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
       BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
       int countBefore = getRegistry().getBeanDefinitionCount();
       documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
       return getRegistry().getBeanDefinitionCount() - countBefore;
    }
  2. Bean Definition解析

    在DefaultBeanDefinitionDocumentReader類中
    DefaultBeanDefinitionDocumentReader 是BeanDefinitionDocumentReader的實現類,這個類來實際的解析<bean/>標籤
    &1.registerBeanDefinitions()也作的前期準備,真正去解析文件的方法是doRegisterBeanDefinitions()
       
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
                  ....
                 doRegisterBeanDefinitions(root);
    }

    &2.doRegisterBeanDefinitions方法將</beans>節點下的每個<bean/>相對應的bean definition註冊。可是真正作這件事的是另外一個方法 parseBeanDefinitions(root, this.delegate);
    protected void doRegisterBeanDefinitions(Element root){
         ....
         parseBeanDefinitions(root, this.delegate);
         ....
    }
    &3.<beans/>中還包含<bean/>元素,須要對bean元素進行解析,parseBeanDefinitions方法中調用來
    parseDefaultElement方法來完成對<bean/>元素的解析,具體分解析過程有processBeanDefinition(ele, delegate)方法來實現,就是對beanDefinition的處理。
  3. Bean Definition處理
      在DefaultBeanDefinitionDocumentReader類中
    &1.
    processBeanDefinition方法中將Element對象轉化成了BeanDefinitionHolder對象。這個BeanDefinitionHolder對象中持有的BeanDefinition實例的引用,還有beanName,還有bean的別名。
          而後將BeanDefinitionHolder對象和特定的bean工廠做爲參數交給BeanDefinitionReaderUtils類來處理來進行註冊。到了實際的註冊步驟啦
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
       BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
       if (bdHolder != null) {
          bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
          try {
             // Register the final decorated instance.
     BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());       }
          catch (BeanDefinitionStoreException ex) {
             getReaderContext().error("Failed to register bean definition with name '" +
                   bdHolder.getBeanName() + "'", ele, ex);
          }
          // Send registration event.
          getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
       }
    }
  4. Bean Definition註冊
    在BeanDefinitionReaderUtils類中

    public static void registerBeanDefinition(
          BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
          throws BeanDefinitionStoreException {

       // Register bean definition under primary name.
       String beanName = definitionHolder.getBeanName();
       registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

       // Register aliases for bean name, if any.
       String[] aliases = definitionHolder.getAliases();
       if (aliases != null) {
          for (String alias : aliases) {
             registry.registerAlias(beanName, alias);
          }
       }
    }

    DefaultListableBeanFactory類中,在這個方法中,將BeanDefinition 註冊到了ConcurrentHashMap對象中了。註冊完成

 

 

 

參考:

https://my.oschina.net/liyurong/blog/1929996