源碼成神之路:Spring Framework源代碼解析之IOC容器(三)

在Spring Framework源代碼解析之IOC容器(一)和Spring Framework源代碼解析之IOC容器(二),我們對Spring IOC做了簡單介紹以及熟悉了一些支持IOC的關鍵類,本文將對IOC的依賴注入特性進行解析,歡迎指正。

載入和註冊

在上文中,我們介紹到XmlBeanFactory對資源文件的載入,並最後引出了一個高帥富——ApplicationContext。接著上文來看,其實我們平時最常用的是Application,因為它不僅具備BeanFactory的全部能力,還為應用程序提供了很多的便利,上文已經說過了,它繼承了很多父類,使它可以具備支持國際化、支持多方式定義資源,支持事件等。我們可以認為BeanFactory和Application是兩個層面的IOC容器,而我們平時開發應用程序就是使用Application。Application有很多抽象子類,如AbstractApplicationContext,在該抽象子類下又有很多具體的實現類,如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext等。我們以FileSystemXmlApplicationContext為例,來看看它載入和註冊資源的過程。

首先通過FileSystemXmlApplicationContext來建立IOC容器:

<code>ApplicationContext = new FileSystemXmlApplicationContext(xmlPath);/<code>

調用構造函數:

<code>/**
* Create a new FileSystemXmlApplicationContext, loading the definitions
* from the given XML files and automatically refreshing the context.
* @param configLocations array of file paths
* @throws BeansException if context creation failed
 */
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
        this(configLocations, true, null);
    }/<code>

實際調用:

<code>public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

 
        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }/<code>

注意方法refresh(),這裡使用了一個“模板方法”的設計模式,refresh()是一個模板方法,具體實現在FileSystemXmlApplicationContext的若干級父類AbstractXmlApplicationContext中:

<code>public void refresh() throws BeansException, IllegalStateException { 
     synchronized (this.startupShutdownMonitor) { 
         synchronized (this.activeMonitor) { 
             this.active = true; 
         } 
    
        // 這裡需要子類來協助完成資源位置定義,bean 載入和向 IOC 容器註冊的過程  
        refreshBeanFactory(); 
         ............ 
}/<code>

refresh()方法包含了整個IOC容器的初始化過程,資源的定位由refreshBeanFactory()來實現,而在AbstractXmlApplicationContext中定義了對資源的讀取過程,默認由 XmlBeanDefinitionReader 來讀取:

<code>protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { 
     // 這裡使用 XMLBeanDefinitionReader 來載入 bean 定義信息的 XML 文件  
     XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);  
     
     //這裡配置 reader 的環境,其中 ResourceLoader 是我們用來定位 bean 定義信息資源位置的  
     ///因為上下文本身實現了 ResourceLoader 接口,所以可以直接把上下文作為 ResourceLoader 傳遞給 XmlBeanDefi
nitionReader  
     beanDefinitionReader.setResourceLoader(this); 
     beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); 

    
     initBeanDefinitionReader(beanDefinitionReader); 
     //這裡轉到定義好的 XmlBeanDefinitionReader 中對載入 bean 信息進行處理 
     loadBeanDefinitions(beanDefinitionReader); 
}/<code>

轉到beanDefinitionReader中進行處理:

<code>protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOExcepti
on {  
     Resource[] configResources = getConfigResources(); 
     if (configResources != null) { 
         //調用 XmlBeanDefinitionReader 來載入 bean 定義信息。 
         reader.loadBeanDefinitions(configResources); 
     } 
     String[] configLocations = getConfigLocations(); 
     if (configLocations != null) { 
         reader.loadBeanDefinitions(configLocations); 
     } 
}/<code>

完成了載入,我們來分析註冊,來到DefaultListableBeanFactory中,它通過HashMap來持有載入的BeanDefinition:

<code>/** Map of bean definition objects, keyed by bean name */
    private final Map<string> beanDefinitionMap = new ConcurrentHashMap<string>();/<string>/<string>/<code>

跟蹤代碼,找到註冊的具體實現類DefaultListableBeanFactoy:

<code>//---------------------------------------------------------------------
    // Implementation of BeanDefinitionRegistry interface
    //---------------------------------------------------------------------
 
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
 
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
 
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {

                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
 
        synchronized (this.beanDefinitionMap) {
            //這裡檢查是不是有名字相同的BeanDefinition已經在IOC容器中註冊,如果有但不允許覆蓋則拋出異常
            Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
            if (oldBeanDefinition != null) {
                if (!this.allowBeanDefinitionOverriding) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                            "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                            "': There is already [" + oldBeanDefinition + "] bound.");
                }
                else {
                    if (this.logger.isInfoEnabled()) {
                        this.logger.info("Overriding bean definition for bean '" + beanName +
                                "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                    }
                }
            }
            else {
                this.beanDefinitionNames.add(beanName);
                this.frozenBeanDefinitionNames = null;
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
 
            resetBeanDefinition(beanName);
        }
    }/<code>

完成了註冊,此時我們就是從容器中使用對象了,萬事具備只欠getBean了。

依賴注入

我們記得在BeanFactory中有一個getBean方法,它其實就是觸發依賴注入的入口,getBean的實現我們具體看看DefaultListableBeanFactory的父類AbstractBeanFactory,看看其中getBean的是如何實現的:

<code>public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }/<code>

接著看doGetBean:

<code>1.             protected  T doGetBean(final String name, final Class requiredType,/<code>
<code>2.              final Object[] args, boolean typeCheckOnly) throws BeansException {/<code>
<code>   3:   /<code>
<code>   4:          final String beanName = transformedBeanName(name);/<code>
<code>   5:          Object bean;/<code>
<code>   6:   /<code>
<code>   7:          // Eagerly check singleton cache for manually registered singletons./<code>
<code>   8:          // 先從緩存裡面取,處理已經被創建過的單件模式的bean,對這種bean的獲取不需要重複的創建/<code>
<code>   9:          Object sharedInstance = getSingleton(beanName);/<code>
<code>  10:          if (sharedInstance != null && args == null) {/<code>
<code>  11:              if (logger.isDebugEnabled()) {/<code>
<code>  12:                  if (isSingletonCurrentlyInCreation(beanName)) {/<code>
<code>  13:                      logger.debug("Returning eagerly cached instance of singleton bean '"/<code>
<code>  14:                              + beanName/<code>
<code>  15:                              + "' that is not fully initialized yet - a consequence of a circular reference");/<code>
<code>  16:                  } else {/<code>
<code>  17:                      logger.debug("Returning cached instance of singleton bean '"/<code>
<code>  18:                              + beanName + "'");/<code> 
<code>  19:                  }/<code>
<code>  20:              }/<code>
<code>  21:              bean = getObjectForBeanInstance(sharedInstance, name, beanName,/<code>
<code>  22:                      null);/<code>
<code>  23:          }/<code>
<code>  24:   /<code>
<code>  25:          else {/<code>
<code>  26:              // Fail if we're already creating this bean instance:/<code>
<code>  27:              // We're assumably within a circular reference./<code>
<code>  28:              if (isPrototypeCurrentlyInCreation(beanName)) {/<code>
<code>  29:                  throw new BeanCurrentlyInCreationException(beanName);/<code>
<code>  30:              }/<code>
<code>  31:   /<code>
<code>  32:              // Check if bean definition exists in this factory./<code>
<code>  33:              BeanFactory parentBeanFactory = getParentBeanFactory();/<code>
<code>  34:              if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {/<code>
<code>  35:                  // Not found -> check parent./<code>
<code>  36:                  String nameToLookup = originalBeanName(name);/<code>
<code>  37:                  if (args != null) {/<code>
<code>  38:                      // Delegation to parent with explicit args./<code>
<code>  39:                      return (T) parentBeanFactory.getBean(nameToLookup, args);/<code>
<code>  40:                  } else {/<code>
<code>  41:                      // No args -> delegate to standard getBean method./<code>
<code>  42:                      return parentBeanFactory/<code>
<code>  43:                              .getBean(nameToLookup, requiredType);/<code> 
<code>  44:                  }/<code>
<code>  45:              }/<code>
<code>  46:   /<code>
<code>  47:              if (!typeCheckOnly) {/<code>
<code>  48:                  markBeanAsCreated(beanName);/<code>
<code>  49:              }/<code>
<code>  50:              // 這裡根據bean的名字取得BeanDefinition/<code>
<code>  51:              final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);/<code>
<code>  52:              checkMergedBeanDefinition(mbd, beanName, args);/<code>
<code>  53:   /<code>
<code>  54:              // Guarantee initialization of beans that the current bean depends/<code>
<code>  55:              // on./<code>
<code>  56:              // 取當前bean的所有依賴的bean,這樣會觸發getBean的遞歸調用,直至取到一個沒有任何依賴的bean為止/<code>
<code>  57:              String[] dependsOn = mbd.getDependsOn();/<code>
<code>  58:              if (dependsOn != null) {/<code>
<code>  59:                  for (String dependsOnBean : dependsOn) {/<code>
<code>  60:                      getBean(dependsOnBean);/<code>
<code>  61:                      registerDependentBean(dependsOnBean, beanName);/<code>
<code>  62:                  }/<code>
<code>  63:              }/<code>
<code>  64:   /<code>
<code>  65:              // Create bean instance./<code>
<code>  66:              // 這裡創建單例的實例,調用createBean方法/<code> 
<code>  67:              if (mbd.isSingleton()) {/<code>
<code>  68:                  sharedInstance = getSingleton(beanName,/<code>
<code>  69:                          new ObjectFactory<object>() {/<object>/<code>
<code>  70:                              public Object getObject() throws BeansException {/<code>
<code>  71:                                  try {/<code>
<code>  72:                                      return createBean(beanName, mbd, args);/<code>
<code>  73:                                  } catch (BeansException ex) {/<code>
<code>  74:                                      // Explicitly remove instance from singleton/<code>
<code>  75:                                      // cache: It might have been put there/<code>
<code>  76:                                      // eagerly by the creation process, to allow/<code>
<code>  77:                                      // for circular reference resolution./<code>
<code>  78:                                      // Also remove any beans that received a/<code>
<code>  79:                                      // temporary reference to the bean./<code>
<code>  80:                                      destroySingleton(beanName);/<code>
<code>  81:                                      throw ex;/<code>
<code>  82:                                  }/<code>
<code>  83:                              }/<code>
<code>  84:                          });/<code>
<code>  85:                  bean = getObjectForBeanInstance(sharedInstance, name, beanName,/<code>
<code>  86:                          mbd);/<code>
<code>  87:              }/<code>
<code>  88:              // 這裡則是創建prototype bean的地方/<code>
<code>  89:              else if (mbd.isPrototype()) {/<code>
<code>  90:                  // It's a prototype -> create a new instance./<code>
<code>  91:                  Object prototypeInstance = null;/<code> 
<code>  92:                  try {/<code>
<code>  93:                      beforePrototypeCreation(beanName);/<code>
<code>  94:                      prototypeInstance = createBean(beanName, mbd, args);/<code>
<code>  95:                  } finally {/<code>
<code>  96:                      afterPrototypeCreation(beanName);/<code>
<code>  97:                  }/<code>
<code>  98:                  bean = getObjectForBeanInstance(prototypeInstance, name,/<code>
<code>  99:                          beanName, mbd);/<code>
<code> 100:              }/<code>
<code> 101:   /<code>
<code> 102:              else {/<code>
<code> 103:                  String scopeName = mbd.getScope();/<code>
<code> 104:                  final Scope scope = this.scopes.get(scopeName);/<code>
<code> 105:                  if (scope == null) {/<code>
<code> 106:                      throw new IllegalStateException(/<code>
<code> 107:                              "No Scope registered for scope '" + scopeName + "'");/<code>
<code> 108:                  }/<code>
<code> 109:                  try {/<code>
<code> 110:                      Object scopedInstance = scope.get(beanName,/<code>
<code> 111:                              new ObjectFactory<object>() {/<object>/<code>
<code> 112:                                  public Object getObject() throws BeansException {/<code>
<code> 113:                                      beforePrototypeCreation(beanName);/<code>
<code> 114:                                      try {/<code>
<code> 115:                                          return createBean(beanName, mbd, args);/<code>
<code> 116:                                      } finally {/<code> 
<code> 117:                                          afterPrototypeCreation(beanName);/<code>
<code> 118:                                      }/<code>
<code> 119:                                  }/<code>
<code> 120:                              });/<code>
<code> 121:                      bean = getObjectForBeanInstance(scopedInstance, name,/<code>
<code> 122:                              beanName, mbd);/<code>
<code> 123:                  } catch (IllegalStateException ex) {/<code>
<code> 124:                      throw new BeanCreationException(/<code>
<code> 125:                              beanName,/<code>
<code> 126:                              "Scope '"/<code>
<code> 127:                                      + scopeName/<code>
<code> 128:                                      + "' is not active for the current thread; "/<code>
<code> 129:                                      + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",/<code>
<code> 130:                              ex);/<code>
<code> 131:                  }/<code>
<code> 132:              }/<code>
<code> 133:          }/<code>
<code> 134:   /<code>
<code> 135:          // Check if required type matches the type of the actual bean instance./<code>
<code> 136:          // 這裡對創建出來bean進行類型的檢查,如果沒有問題,就返回這個新創建的bean/<code>
<code> 137:          if (requiredType != null && bean != null/<code>
<code> 138:                  && !requiredType.isAssignableFrom(bean.getClass())) {/<code>
<code> 139:              try {/<code>
<code> 140:                  return getTypeConverter()/<code>
<code> 141:                          .convertIfNecessary(bean, requiredType);/<code>
<code> 142:              } catch (TypeMismatchException ex) {/<code>
<code> 143:                  if (logger.isDebugEnabled()) {/<code>
<code> 144:                      logger.debug(/<code>
<code> 145:                              "Failed to convert bean '" + name/<code>
<code> 146:                                      + "' to required type ["/<code>
<code> 147:                                      + ClassUtils.getQualifiedName(requiredType)/<code>
<code> 148:                                      + "]", ex);/<code>
<code> 149:                  }/<code>
<code> 150:                  throw new BeanNotOfRequiredTypeException(name, requiredType,/<code>
<code> 151:                          bean.getClass());/<code>
<code> 152:              }/<code>
<code> 153:          }/<code>
<code> 154:          return (T) bean;/<code>
<code> 155:      }/<code>

具體創建對象在createBean裡面,來看看createBean:

<code>   1:  protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)/<code>
<code>   2:              throws BeanCreationException {/<code>
<code>   3:   /<code>
<code>   4:          if (logger.isDebugEnabled()) {/<code>
<code>   5:              logger.debug("Creating instance of bean '" + beanName + "'");/<code>
<code>   6:          }/<code>
<code>   7:          // Make sure bean class is actually resolved at this point./<code>
<code>   8:          resolveBeanClass(mbd, beanName);/<code> 
<code>   9:   /<code>
<code>  10:          // Prepare method overrides./<code>
<code>  11:          try {/<code>
<code>  12:              mbd.prepareMethodOverrides();/<code>
<code>  13:          }/<code>
<code>  14:          catch (BeanDefinitionValidationException ex) {/<code>
<code>  15:              throw new BeanDefinitionStoreException(mbd.getResourceDescription(),/<code>
<code>  16:                      beanName, "Validation of method overrides failed", ex);/<code>
<code>  17:          }/<code>
<code>  18:   /<code>
<code>  19:          try {/<code>
<code>  20:              // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance./<code>
<code>  21:              Object bean = resolveBeforeInstantiation(beanName, mbd);/<code>
<code>  22:              if (bean != null) {/<code>
<code>  23:                  return bean;/<code>
<code>  24:              }/<code>
<code>  25:          }/<code>
<code>  26:          catch (Throwable ex) {/<code>
<code>  27:              throw new BeanCreationException(mbd.getResourceDescription(), beanName,/<code>
<code>  28:                      "BeanPostProcessor before instantiation of bean failed", ex);/<code>
<code>  29:          }/<code>
<code>  30:          //這裡是創建bean的調用/<code>
<code>  31:          Object beanInstance = doCreateBean(beanName, mbd, args);/<code>
<code>  32:          if (logger.isDebugEnabled()) {/<code>
<code>  33:              logger.debug("Finished creating instance of bean '" + beanName + "'");/<code> 
<code>  34:          }/<code>
<code>  35:          return beanInstance;/<code>
<code>  36:      }/<code>

又看doCreateBean,^_^遭不住啊。。

<code>   1:  protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {/<code>
<code>   2:          // Instantiate the bean./<code>
<code>   3:          BeanWrapper instanceWrapper = null;/<code>
<code>   4:          if (mbd.isSingleton()) {/<code>
<code>   5:              instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);/<code>
<code>   6:          }/<code>
<code>   7:          if (instanceWrapper == null) {/<code>
<code>   8:              instanceWrapper = createBeanInstance(beanName, mbd, args);/<code>
<code>   9:          }/<code>
<code>  10:          ........./<code>
<code>  11:          /<code>
<code>  12:      }/<code>

具體創建對象的方法是createBeanInstance:

<code>   1:  protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {/<code>
<code>   2:          // Make sure bean class is actually resolved at this point./<code>
<code>   3:          Class beanClass = resolveBeanClass(mbd, beanName);/<code>
<code>   4:   /<code>
<code>   5:          if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {/<code>
<code>   6:              throw new BeanCreationException(mbd.getResourceDescription(), beanName,/<code>
<code>   7:                      "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());/<code>
<code>   8:          }/<code>
<code>   9:          //這裡使用工廠方法對bean進行實例化/<code>
<code>  10:          if (mbd.getFactoryMethodName() != null)  {/<code>
<code>  11:              return instantiateUsingFactoryMethod(beanName, mbd, args);/<code>
<code>  12:          }/<code>
<code>  13:   /<code>
<code>  14:          // Shortcut when re-creating the same bean.../<code>
<code>  15:          boolean resolved = false;/<code>
<code>  16:          boolean autowireNecessary = false;/<code>
<code>  17:          if (args == null) {/<code>
<code>  18:              synchronized (mbd.constructorArgumentLock) {/<code>
<code>  19:                  if (mbd.resolvedConstructorOrFactoryMethod != null) {/<code>
<code>  20:                      resolved = true;/<code>
<code>  21:                      autowireNecessary = mbd.constructorArgumentsResolved;/<code>
<code>  22:                  }/<code>
<code>  23:              }/<code>
<code>  24:          }/<code>
<code>  25:          if (resolved) {/<code>
<code>  26:              if (autowireNecessary) {/<code>
<code>  27:                  return autowireConstructor(beanName, mbd, null, null);/<code>
<code>  28:              }/<code>
<code>  29:              else {/<code>
<code>  30:                  return instantiateBean(beanName, mbd);/<code>
<code>  31:              }/<code>
<code>  32:          }/<code> 
<code>  33:   /<code>
<code>  34:          // Need to determine the constructor.../<code>
<code>  35:          //使用構造函數進行實例化/<code>
<code>  36:          Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);/<code>
<code>  37:          if (ctors != null ||/<code>
<code>  38:                  mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||/<code>
<code>  39:                  mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {/<code>
<code>  40:              return autowireConstructor(beanName, mbd, ctors, args);/<code>
<code>  41:          }/<code>
<code>  42:   /<code>
<code>  43:          // No special handling: simply use no-arg constructor./<code>
<code>  44:          //使用默認的構造函數對bean進行實例化/<code>
<code>  45:          return instantiateBean(beanName, mbd);/<code>
<code>  46:      }/<code>

來看看使用默認的構造函數對bean進行實例化的代碼instantiateBean:

<code>   1:  protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {/<code>
<code>   2:          try {/<code>
<code>   3:              //使用默認的實例化策略對bean進行實例化,默認的實例化策略是CglibSubclassingInstantiationStrategy,也就是用cglib來對bean進行實例化/<code>
<code>   4:              Object beanInstance;/<code>
<code>   5:              final BeanFactory parent = this;/<code>
<code>   6:              if (System.getSecurityManager() != null) {/<code> 
<code>   7:                  beanInstance = AccessController.doPrivileged(new PrivilegedAction<object>() {/<object>/<code>
<code>   8:                      public Object run() {/<code>
<code>   9:                          return getInstantiationStrategy().instantiate(mbd, beanName, parent);/<code>
<code>  10:                      }/<code>
<code>  11:                  }, getAccessControlContext());/<code>
<code>  12:              }/<code>
<code>  13:              else {/<code>
<code>  14:                  beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);/<code>
<code>  15:              }/<code>
<code>  16:              BeanWrapper bw = new BeanWrapperImpl(beanInstance);/<code>
<code>  17:              initBeanWrapper(bw);/<code>
<code>  18:              return bw;/<code>
<code>  19:          }/<code>
<code>  20:          catch (Throwable ex) {/<code>
<code>  21:              throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);/<code>
<code>  22:          }/<code>
<code>  23:      }/<code>

這裡用cglib對bean進行實例化,cglib是一個常用的字節碼生成器的類庫,它提供了一系列的API來提供java字節碼生成和轉換的功能,如果有興趣可以查看cglib的使用文檔。另外生成bean的策略還有很多種,這裡只是選了最常用的方法來介紹。至此,bean實例創建過程就算完成了,然後通過populateBean方法將創建好的實例的依賴關係設置好,最終完成依賴注入的過程,由於篇幅關係這裡就不詳細列舉了,populateBean方法可以在AbstractAutowireCapableBeanFactory中找到。

小結

自己對Spring IOC代碼的學習暫時就到這裡,要搞懂一個特性,確實需要花費很大的功夫,Spring代碼量比較大,而且各個特性之間又有交叉,要梳理清楚不是件容易的事,不過回頭來看自己還是有收穫的,希望對看它的朋友也有一點收穫。

注意注意:以上分享的這些Spring筆記:面試錦集解析+學習筆記+學習導圖+Spring源碼視頻,如果你想要一起學習轉發後關注我私信【資料】免費領取吧


分享到:


相關文章: