Spring的bean加載流程


Spring bean的加載

Spring的bean加載

finishBeanFactoryInitialization(),注釋上面寫着 **Instantiate all remaining (non-lazy-init) singletons**,意味着非延遲加載的類,將在這一步實例化,完成類的加載。

而我們使用到 **context.getBean("beanName")**方法,如果對應的 **bean** 是非延遲加載的,那么直接就能拿出來進行使用,而延遲加載的 **bean** 就需要上面的步驟進行類的加載,加載完之后才能進行使用Spring只是暴露了簡單的接口給調用者。

加載流程:

  • 從開始的getbean入口進行分析

    ApplicationContext context = new ClassPathXmlApplicationContext("配置文件xml");
       context.getBean("bean名字");
    
  • 1、先獲取bean,調用AbstractBeanFactory的doGetBean
    doGetBean有四個參數:

    name:bean的名稱
    requiredType: 返回的類型
    args: 傳遞的構造參數
    typeCheckOnly: 檢查類型

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        //獲取beanName,這邊有三種形式,一個是原始的beanName,一個是加了&的,一個是別名
        final String beanName = transformedBeanName(name);
        Object bean;
    
        // Eagerly check singleton cache for manually registered singletons.
        // 是否已經創建了
        Object sharedInstance = getSingleton(beanName);
        //已經創建了,且沒有構造參數,進入這個方法,如果有構造參數,往else走,也就是說不從獲取bean,而直接創建bean
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 如果是普通bean,直接返回,是FactoryBean,返回他的getObject
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
    
        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            // 沒創建過bean或者是多例的情況或者有參數的情況
            // 創建過Prototype的bean,會循環引用,拋出異常,單例才嘗試解決循環依賴的問題
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
    
            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 父容器存在,本地沒有當前beanName,從父容器取
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                // 處理后,如果是加&,就補上&
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
    
            if (!typeCheckOnly) {
                // typeCheckOnly為false,將beanName放入alreadyCreated中
                markBeanAsCreated(beanName);
            }
    
            try {
                // 獲取BeanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 抽象類檢查
                checkMergedBeanDefinition(mbd, beanName, args);
    
                // Guarantee initialization of beans that the current bean depends on.
                // 如果有依賴的情況,先初始化依賴的bean
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        // 檢查是否循環依賴,a依賴b,b依賴a。包括傳遞的依賴,比如a依賴b,b依賴c,c依賴a
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 注冊依賴關系
                        registerDependentBean(dep, beanName);
                        try {
                            // 初始化依賴的bean
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }
    
                // Create bean instance.
                // 如果是單例
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            // 創建bean
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    // 如果是普通bean,直接返回,是FactoryBean,返回他的getObject
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
    
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        // 加入prototypesCurrentlyInCreation,說明正在創建
                        beforePrototypeCreation(beanName);
                        //創建bean
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        // 移除prototypesCurrentlyInCreation,說明已經創建結束
                        afterPrototypeCreation(beanName);
                    }
                    // 如果是普通bean,直接返回,是FactoryBean,返回他的getObject
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
    
                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
    
        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }
    
  • 2、獲取beanName然后轉換名稱
    解析完配置后創建的 Map,使用的是 beanName 作為 key。見 DefaultListableBeanFactory:

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

    BeanFactory.getBean中傳入的那么,有可能是這幾種情況:

    • 1.bean name,可以直接獲取到定義 BeanDefinition。

      //轉化bean
      protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
              String beanName = this.transformedBeanName(name);
              Object sharedInstance = this.getSingleton(beanName);
              Object bean;
              .......
      
    • 2.alias name,別名,需要轉化。
      如果是 alias name,在解析階段,alias name 和 bean name 的映射關系被注冊到 SimpleAliasRegistry 中。從該注冊器中取到 beanName。見 SimpleAliasRegistry.canonicalName:

      public String canonicalName(String name) {
              String canonicalName = name;
      
              String resolvedName;
              do {
                  resolvedName = (String)this.aliasMap.get(canonicalName);
                  if (resolvedName != null) {
                      canonicalName = resolvedName;
                  }
              } while(resolvedName != null);
      
              return canonicalName;
          }
      
    • 3.factorybean name, 帶 & 前綴,通過它獲取 BeanDefinition 的時候需要去除 & 前綴。
      如果是 factorybean name,表示這是個工廠 bean,有攜帶前綴修飾符 & 的,直接把前綴去掉。見 BeanFactoryUtils.transformedBeanName :

       public static String transformedBeanName(String name) {
              Assert.notNull(name, "'name' must not be null");
              return !name.startsWith("&") ? name : (String)transformedBeanNameCache.computeIfAbsent(name, (beanName) -> {
                  do {
                      beanName = beanName.substring("&".length());
                  } while(beanName.startsWith("&"));
      
                  return beanName;
              });
          }
      

    image

  • 3、合並RootBeanDefinition(合並本地的bean)
    從配置文件讀取的BeanDefinition是 GenericBeanDefinition它的記錄了一些當前類聲明的屬性或構造參數,但是對於父類只用了一個 parentName 來記錄。

    public class GenericBeanDefinition extends AbstractBeanDefinition {
        ...
        private String parentName;
        ...
    }
    

    實例化 Bean 的時候,使用的 BeanDefinition 是 RootBeanDefinition 類型而非 GenericBeanDefinition

    • GenericBeanDefinition 在有繼承關系的情況下,定義的信息不足:
      如果不存在繼承關系,GenericBeanDefinition 存儲的信息是完整的,可以直接轉化為 RootBeanDefinition。
      如果存在繼承關系,GenericBeanDefinition 存儲的是 增量信息 而不是 全量信息。
      image

      • 實際上干活的還是AbstractBeanFactory.doGetBean

        protected <T> T doGetBean ... {
            ...
            
            // 合並父類定義
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                
            ...
                
            // 使用合並后的定義進行實例化
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                
            ...
        }
        
      • 在判斷 parentName 存在的情況下,說明存在父類定義,啟動合並。如果父類還有父類,遞歸調用,繼續合並。

            protected RootBeanDefinition getMergedBeanDefinition(
                    String beanName, BeanDefinition bd, BeanDefinition containingBd)
                    throws BeanDefinitionStoreException {
        
                ...
                
                String parentBeanName = transformedBeanName(bd.getParentName());
        
                ...
                
                // 遞歸調用,繼續合並父類定義
                pbd = getMergedBeanDefinition(parentBeanName);
                
                ...
        
                // 使用合並后的完整定義,創建 RootBeanDefinition
                mbd = new RootBeanDefinition(pbd);
                
                // 使用當前定義,對 RootBeanDefinition 進行覆蓋
                mbd.overrideFrom(bd);
        
                ...
                return mbd;
            }
        
        

        每次合並完父類定義后,都會調用 RootBeanDefinition.overrideFrom 對父類的定義進行覆蓋,獲取到當前類能夠正確實例化的 全量信息。

    • 解決循環依賴的問題(暫時說一下,以后詳細分析)
      假設TestA中需要注入TestB,TestB中需要注入TestA。
      對象創建成功后,會在singletonFactories中保存一個對象工廠ObjectFactory,調用這個ObjectFactory的getObject()就可以在任何地方獲取剛創建的對象。
      這樣當TestB在獲取TestA的時候,發現singletonFactories中有個工廠可以獲取到TestA,那么就直接調用他,最后會進入下面這個方法

      protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
         Object exposedObject = bean;
         if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            List<SmartInstantiationAwareBeanPostProcessor> smartInstantiationAware = getBeanPostProcessorCache().smartInstantiationAware;
            for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
               exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
            }
         }
         return exposedObject;
      }
      
      
      

      所有實現了SmartInstantiationAwareBeanPostProcessor接口類的getEarlyBeanReference()嘗試做最后的修改,這個方法返回的只是傳遞過來的對象。
      這樣依賴循環就解決了。

  • 4、創建實例
    獲取到完整的 RootBeanDefintion 后,就可以拿這份定義信息來實例具體的 Bean。(創建實例由AbstractAutowireCapableBeanFactory接手,在spring容器架構里面有具體內容)
    源碼解析:具體實例創建見 AbstractAutowireCapableBeanFactory.createBeanInstance

    //調用解析方法解析轉進來的Bean
    Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    //如果傳入的不為空並且修飾符不是公開的(獲取兩個對象的修飾權限)也就是不為空的時判斷是否有他們的訪問權限
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    } 
    
    else {
    //是否有其他的類將本地bean實例了
     Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
         //如果不為空就就意味着他已經被實例化直接返回已經被其他調用者實例化方法 
                if (instanceSupplier != null) {
                    return this.obtainFromSupplier(instanceSupplier, beanName);
            //如果不為空就意味着被工廠方法調用實例化直接返回方法,被工廠方法使用實例化了
                } else if (mbd.getFactoryMethodName() != null) {
                    return this.instantiateUsingFactoryMethod(beanName, mbd, args);
                } else {
         // 判斷是否已經解析過了
           boolean resolved = false;
            // 為false說明無參,true有參
                    boolean autowireNecessary = false;
                    if (args == null) {
                        synchronized(mbd.constructorArgumentLock) {
              //如果已經被解析過了
                            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                                resolved = true;
                                autowireNecessary = mbd.constructorArgumentsResolved;
                            }
                        }
                    }
           // 解析過了,根據是否有參數選擇無參構造還是有參構造
             if (resolved) {
                        return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
                    }
           // 根據bean的定義解析參數
            else {
                        Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                        if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
                            ctors = mbd.getPreferredConstructors();
                            return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
                        }
                      //  構造器注入
                        else {
                            return this.autowireConstructor(beanName, mbd, ctors, args);
                        }
                    }
                }
            }
        }
    
    
    
    • 返回 Bean 的包裝類 BeanWrapper,一共有三種策略:

      • 使用工廠方法創建,instantiateUsingFactoryMethod
        使用工廠方法創建,會先使用 getBean 獲取工廠類,然后通過參數找到匹配的工廠方法,調用實例化方法實現實例化,具體見
        ConstructorResolver.instantiateUsingFactoryMethod

        public BeanWrapper instantiateUsingFactoryMethod ... (
            ...
            String factoryBeanName = mbd.getFactoryBeanName();
            ...
            factoryBean = this.beanFactory.getBean(factoryBeanName);
            ...
            // 匹配正確的工廠方法
            ...
            beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(...);
            ...
            bw.setBeanInstance(beanInstance);
            return bw;
        }
        
        
      • 使用無參構造函數創建,instantiateBean
        使用無參構造函數創建是最簡單的方式,見 AbstractAutowireCapableBeanFactory.instantiateBean:

        protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
            try {
                Object beanInstance;
                final BeanFactory parent = this;
                if (System.getSecurityManager() != null) {
                    beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                            getInstantiationStrategy().instantiate(mbd, beanName, parent),
                            getAccessControlContext());
                }
                else {
                    // 創建一個bean
                    beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
                }
                // 初始化BeanWrapper並返回
                BeanWrapper bw = new BeanWrapperImpl(beanInstance);
                initBeanWrapper(bw);
                return bw;
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
            }
        }
        
        
      • 使用有參構造函數創建,autowireConstructor
        使用有參構造函數創建,整個過程比較復雜,涉及到參數和構造器的匹配。為了找到匹配的構造器,Spring 花了大量的工作,見 ConstructorResolver.autowireConstructor :

        public BeanWrapper autowireConstructor ... {
            ...
            Constructor<?> constructorToUse = null;
            ...
            // 匹配構造函數的過程
            ...
            beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(...);
            ...
            bw.setBeanInstance(beanInstance);
            return bw;
        }           
        
        

      拿到了構造函數,並沒有立即實例化。因為用戶使用了 replace 和 lookup 的配置方法,用到了動態代理加入對應的邏輯。如果沒有的話,直接使用反射來創建實例。
      創建實例后,就可以開始注入屬性和初始化等操作。
      如果是 FactoryBean 的話需要使用 getObject 方法來創建實例。見 AbstractBeanFactory.getObjectForBeanInstance ,會執行到 FactoryBeanRegistrySupport.doGetObjectFromFactoryBean 。

      • getObjectForBeanInstance 源碼:

        protected Object getObjectForBeanInstance(
                    Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
        
            // Don't let calling code try to dereference the factory if the bean isn't a factory.
            // 如果beanname是&開頭的,這個bean必須是FactoryBean類型
            if (BeanFactoryUtils.isFactoryDereference(name)) {
                if (beanInstance instanceof NullBean) {
                    return beanInstance;
                }
                if (!(beanInstance instanceof FactoryBean)) {
                    throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
                }
            }
        
            // Now we have the bean instance, which may be a normal bean or a FactoryBean.
            // If it's a FactoryBean, we use it to create a bean instance, unless the
            // caller actually wants a reference to the factory.
            // 普通bean或者beanname是&開頭的,返回beanInstance
            if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
                return beanInstance;
            }
        
            // 是FactoryBean但是沒有&開頭的
            Object object = null;
            if (mbd == null) {
                // bean的定義信息是空的,從緩存中拿
                object = getCachedObjectForFactoryBean(beanName);
            }
            if (object == null) {
                //緩存不存在
                // Return bean instance from factory.
                FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
                // Caches object obtained from FactoryBean if it is a singleton.
                // mdb為空,並且已經實例化過
                if (mbd == null && containsBeanDefinition(beanName)) {
                    mbd = getMergedLocalBeanDefinition(beanName);
                }
                // 是否是用戶定義的,而不是程序本身定義的
                boolean synthetic = (mbd != null && mbd.isSynthetic());
                object = getObjectFromFactoryBean(factory, beanName, !synthetic);//返回factory的getObject方法
            }
            return object;
        }
        
        
      • doGetObjectFromFactoryBean源碼:

        //調用factoryBean的getObjectType方法返回對象
        private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
                    throws BeanCreationException {
        
            Object object;
            try {
                if (System.getSecurityManager() != null) {
                    AccessControlContext acc = getAccessControlContext();
                    try {
                        object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                    }
                    catch (PrivilegedActionException pae) {
                        throw pae.getException();
                    }
                }
                else {
                    object = factory.getObject();//調用factoryBean的getObjectType方法返回對象
                }
            }
            catch (FactoryBeanNotInitializedException ex) {
                throw new BeanCurrentlyInCreationException(beanName, ex.toString());
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
            }
        
            // Do not accept a null value for a FactoryBean that's not fully
            // initialized yet: Many FactoryBeans just return null then.
            if (object == null) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(
                            beanName, "FactoryBean which is currently in creation returned null from getObject");
                }
                //沒獲取到對象,返回NullBean
                object = new NullBean();
            }
            return object;
        }
        
        
        
        
  • 5、注入屬性

    • 實例創建完后開始進行屬性的注入,如果涉及到外部依賴的實例,會自動檢索並關聯到該當前實例。入口方法在AbstractAutowireCapableBeanFactory.populateBean。

      protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {  
          if (bw == null) {
              // 如果BeanWrapper為空,但是有屬性值,就跑異常
              if (mbd.hasPropertyValues()) {
                  throw new BeanCreationException(
                          mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
              }
              else {
                  // Skip property population phase for null instance.
                  return;
              }
          }
      
          // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
          // state of the bean before properties are set. This can be used, for example,
          // to support styles of field injection.
          // 看看InstantiationAwareBeanPostProcessors是否有注入值,如果有注入,就不繼續注入,直接返回
          boolean continueWithPropertyPopulation = true;
      
          if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
              for (BeanPostProcessor bp : getBeanPostProcessors()) {
                  if (bp instanceof InstantiationAwareBeanPostProcessor) {
                      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                      if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                          continueWithPropertyPopulation = false;
                          break;
                      }
                  }
              }
          }
      
          if (!continueWithPropertyPopulation) {
              return;
          }
      
          PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
      
          if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
              // 拷貝配置信息
              MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
              // Add property values based on autowire by name if applicable.
              // 根據名稱注入
              if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
                  autowireByName(beanName, mbd, bw, newPvs);
              }
              // Add property values based on autowire by type if applicable.
              // 根據類型注入
              if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
                  autowireByType(beanName, mbd, bw, newPvs);
              }
              pvs = newPvs;
          }
          // r容器是否有InstantiationAwareBeanPostProcessors
          boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
          // 是否進行依賴檢查
          boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
      
          PropertyDescriptor[] filteredPds = null;
          if (hasInstAwareBpps) {
              if (pvs == null) {
                  pvs = mbd.getPropertyValues();
              }
              // 后置處理
              for (BeanPostProcessor bp : getBeanPostProcessors()) {
                  if (bp instanceof InstantiationAwareBeanPostProcessor) {
                      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                      PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                      if (pvsToUse == null) {
                          if (filteredPds == null) {
                              filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                          }
                          pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                          if (pvsToUse == null) {
                              return;
                          }
                      }
                      pvs = pvsToUse;
                  }
              }
          }
          if (needsDepCheck) {
              if (filteredPds == null) {
                  // 過濾出需要依賴檢查的屬性
                  filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
              }
              // 檢查依賴關系,保證依賴項已初始化
              checkDependencies(beanName, mbd, filteredPds, pvs);
          }
      
          if (pvs != null) {
              // 此時才開始賦值
              applyPropertyValues(beanName, mbd, bw, pvs);
          }
      }
      
      

      應用 InstantiationAwareBeanPostProcessor 處理器,在屬性注入前后進行處理。假設我們使用了 @Autowire 注解,這里會調用到 AutowiredAnnotationBeanPostProcessor 來對依賴的實例進行檢索和注入的,它是 InstantiationAwareBeanPostProcessor 的子類。
      根據名稱或者類型進行自動注入,存儲結果到 PropertyValues 中。
      應用 PropertyValues,填充到 BeanWrapper。這里在檢索依賴實例的引用的時候,會遞歸調用 BeanFactory.getBean 來獲得。

  • 6、初始化

    • 1、觸發Aware,Spring 在初始化階段,如果判斷 Bean 實現了這幾個接口之一,就會往 Bean 中注入它關心的資源。見 AbstractAutowireCapableBeanFactory.invokeAwareMethos :

      protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
              throws Throwable {
      
          boolean isInitializingBean = (bean instanceof InitializingBean);
          // 如果是InitializingBean並且有afterPropertiesSet,調用afterPropertiesSet方法
          if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
              if (logger.isTraceEnabled()) {
                  logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
              }
              if (System.getSecurityManager() != null) {
                  try {
                      AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                          ((InitializingBean) bean).afterPropertiesSet();
                          return null;
                      }, getAccessControlContext());
                  }
                  catch (PrivilegedActionException pae) {
                      throw pae.getException();
                  }
              }
              else {
                  ((InitializingBean) bean).afterPropertiesSet();
              }
          }
          // 如果是InitializingBean,但沒有afterPropertiesSet,調用自定義的方法
          if (mbd != null && bean.getClass() != NullBean.class) {
              String initMethodName = mbd.getInitMethodName();
              if (StringUtils.hasLength(initMethodName) &&
                      !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                      !mbd.isExternallyManagedInitMethod(initMethodName)) {
                  invokeCustomInitMethod(beanName, bean, mbd);
              }
          }
      }
      
      
    • 2、觸發 BeanPostProcessor,Spring 框架提供了 BeanPostProcessor 來達成這個目標。

      /** BeanPostProcessors to apply in createBean */
      private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
      
      

      Bean 實例化前后,Spring 會去調用我們已經注冊的 beanPostProcessors 把處理器都執行一遍。

      public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
              throws BeansException {
      
          Object result = existingBean;
          // 獲取BeanPostProcessor處理
          for (BeanPostProcessor processor : getBeanPostProcessors()) {
              Object current = processor.postProcessBeforeInitialization(result, beanName);
              if (current == null) {
                  return result;
              }
              result = current;
          }
          return result;
      }
      
      
      public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
              throws BeansException {
      
          Object result = existingBean;
          // 獲取BeanPostProcessor處理
          for (BeanPostProcessor processor : getBeanPostProcessors()) {
              Object current = processor.postProcessAfterInitialization(result, beanName);
              if (current == null) {
                  return result;
              }
              result = current;
          }
          return result;
      }
      
      

      這里使用了責任鏈模式,Bean 會在處理器鏈中進行傳遞和處理。當我們調用 BeanFactory.getBean 的后,執行到 Bean 的初始化方法 AbstractAutowireCapableBeanFactory.initializeBean 會啟動這些處理器。

      public Object initializeBean(Object existingBean, String beanName) {
          return initializeBean(beanName, existingBean, null);
      }
      protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
          if (System.getSecurityManager() != null) {
              AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                  invokeAwareMethods(beanName, bean);
                  return null;
              }, getAccessControlContext());
          }
          else {
              // 調用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
              invokeAwareMethods(beanName, bean);
          }
      
          Object wrappedBean = bean;
          if (mbd == null || !mbd.isSynthetic()) {
              // 前置處理器
              wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
          }
      
          try {
              // 初始化方法
              invokeInitMethods(beanName, wrappedBean, mbd);
          }
          catch (Throwable ex) {
              throw new BeanCreationException(
                      (mbd != null ? mbd.getResourceDescription() : null),
                      beanName, "Invocation of init method failed", ex);
          }
          if (mbd == null || !mbd.isSynthetic()) {
              // 后置處理器
              wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
          }
      
          return wrappedBean;
      }
      
      
    • 3、觸發自定義init
      自定義初始化有兩種方式可以選擇:
      實現 InitializingBean。提供了一個很好的機會,在屬性設置完成后再加入自己的初始化邏輯。 定義 init 方法。自定義的初始化邏輯。 見 AbstractAutowireCapableBeanFactory.invokeInitMethods :

      protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
              throws Throwable {
      
          boolean isInitializingBean = (bean instanceof InitializingBean);
          // 如果是InitializingBean並且有afterPropertiesSet,調用afterPropertiesSet方法
          if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
              if (logger.isTraceEnabled()) {
                  logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
              }
              if (System.getSecurityManager() != null) {
                  try {
                      AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                          ((InitializingBean) bean).afterPropertiesSet();
                          return null;
                      }, getAccessControlContext());
                  }
                  catch (PrivilegedActionException pae) {
                      throw pae.getException();
                  }
              }
              else {
                  ((InitializingBean) bean).afterPropertiesSet();
              }
          }
          // 如果是InitializingBean,但沒有afterPropertiesSet,調用自定義的方法
          if (mbd != null && bean.getClass() != NullBean.class) {
              String initMethodName = mbd.getInitMethodName();
              if (StringUtils.hasLength(initMethodName) &&
                      !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                      !mbd.isExternallyManagedInitMethod(initMethodName)) {
                  invokeCustomInitMethod(beanName, bean, mbd);
              }
          }
      }
      
      
  • 7、類型轉換
    Bean 已經加載完畢,屬性也填充好了,初始化也完成了。
    在返回給調用者之前,還留有一個機會對 Bean 實例進行類型的轉換。見 AbstractBeanFactory.doGetBean :

    //調用dogetBean方法
    //以下方法基本都是對dogetbean參數的判斷
      protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
     //       獲取bean后將轉換后的bean賦值給beanName
        String beanName = this.transformedBeanName(name);
            Object bean;
       // 獲取上方單例bean
        Object sharedInstance = this.getSingleton(beanName);
        //判斷是否有單例BEAN,如果有BEAN並且沒有args參數進入此方法
            if (sharedInstance != null && args == null) {
         //   判斷是否啟用日志追蹤
                if (this.logger.isTraceEnabled()) {
           //      判斷獲取的單例bean是否已經加載了
                    if (this.isSingletonCurrentlyInCreation(beanName)) {
             //    在日志里面記錄這條消息
                        this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
             //           如果獲取的單例bean沒有加載就紀錄這條               
             } else {
                        this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                    }
                }
              //  普通的bean直接返回FactoryBean,返回他的getObject
                bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
          //  如果沒有單例BEAN,或者有BEAN並且有args參數進入此方法
        } else {
              //沒創建過bean或者是多例的情況或者有參數的情況
                  //創建過Prototype的bean,會循環引用,拋出異常,單例才嘗試解決循環依賴的問題
                if (this.isPrototypeCurrentlyInCreation(beanName)) {
           //   就拋出異常   Bean 當前正在創建異常
                    throw new BeanCurrentlyInCreationException(beanName);
                }
          
            //     獲取父類工廠
                BeanFactory parentBeanFactory = this.getParentBeanFactory();
          //如果父類工廠不為空,beanName不存在也就是沒有拿到本地的bean
                if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
          //          給調用者原始bean
            String nameToLookup = this.originalBeanName(name);
            //如果父類工廠實例抽象bean工廠
                    if (parentBeanFactory instanceof AbstractBeanFactory) {
             //返回抽象抽象bean工廠的父類工廠,調用dogetbean方法
                        return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                    }
             //        如果參數不為空
                    if (args != null) {
                        return parentBeanFactory.getBean(nameToLookup, args);
                    }
             //         requiredType: 返回的類型
                    if (requiredType != null) {
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
             //         nameToLookup要查找的名稱
                    return parentBeanFactory.getBean(nameToLookup);
                }
            //       如果檢查類型不為空
                if (!typeCheckOnly) {
            //  markBeanAsCreated將 Bean 標記為已創建
                    this.markBeanAsCreated(beanName);
                }
    
                try {
              //獲取本地的BeanDefinition(獲取合並的本地 Bean 定義也即是BeanDefinition)
                    RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
            //檢查合並BeanDefinition
                    this.checkMergedBeanDefinition(mbd, beanName, args);
            //通過本地的BeanDefinition獲取他的依賴
                    String[] dependsOn = mbd.getDependsOn();
                    String[] var11;
            //如果依賴不為空
                    if (dependsOn != null) {
            //將獲取的依賴給數組賦值
                        var11 = dependsOn;
              //將依賴的大小作為界值
                        int var12 = dependsOn.length;
                //        循環賦值
                        for(int var13 = 0; var13 < var12; ++var13) {
                            String dep = var11[var13];
                // 檢查是否循環依賴,a依賴b,b依賴a。包括傳遞的依賴,比如a依賴b,b依賴c,c依賴a
                            if (this.isDependent(beanName, dep)) {
               // 拋出異常,單例才嘗試解決循環依賴的問題
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                            }
                //            注冊依賴關系
                            this.registerDependentBean(dep, beanName);
                            try {
                //當前調用者獲取依賴
                                this.getBean(dep);
                bean的定義異常
                            } catch (NoSuchBeanDefinitionException var24) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                            }
                        }
                    }
                  //  如果本地的BeanDefinition是單例
                    if (mbd.isSingleton()) {
               // 給調用者創建一個BeanDefinition
                        sharedInstance = this.getSingleton(beanName, () -> {
                            try {
                //創建bean
                                return this.createBean(beanName, mbd, args);
                //  bean異常,銷毀
                            } catch (BeansException var5) {
                                this.destroySingleton(beanName);
                                throw var5;
                            }
                        });
             // 如果是普通bean,直接返回,是FactoryBean,返回他的getObject
                        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                  //  本地BeanDefinition是最初的bean(就是原型bean)
            } else if (mbd.isPrototype()) {
                        var11 = null;
                   //     定義一個原型bean
                        Object prototypeInstance;
                        try {
               // 加入一個prototypesCurrentlyInCreation
                            this.beforePrototypeCreation(beanName);
                //在創建原型bean前創建一個beanBeanDefinition
                            prototypeInstance = this.createBean(beanName, mbd, args);
               //         最終移除prototypesCurrentlyInCreation
              } finally {
                            this.afterPrototypeCreation(beanName);
                        }
                    //    如果是普通bean,直接返回,是FactoryBean,返回他的getObject
                        bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    
            } else {
            //獲取本地的BeanDefinition的作用域
                        String scopeName = mbd.getScope();
             // 通過全局作用域獲取當前bean
                        Scope scope = (Scope)this.scopes.get(scopeName);
              //  如果作用域為空則bean不存在
                        if (scope == null) {
             // 拋出異常,bean狀態異常
                            throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                        }
    
                        try {
              //加入一個prototypesCurrentlyInCreation
                            Object scopedInstance = scope.get(beanName, () -> {
              //  在創建原型bean前創建一個beanBeanDefinition
                                this.beforePrototypeCreation(beanName);
    
                                Object var4;
                                try {
                                    var4 = this.createBean(beanName, mbd, args);
                    //最終移除prototypesCurrentlyInCreation
                                } finally {
                                    this.afterPrototypeCreation(beanName);
                                }
    
                                return var4;
                            });
               // 如果是普通bean,直接返回,是FactoryBean,返回他的getObject
                            bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                        } catch (IllegalStateException var23) {
                            throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
                        }
                    }
                } catch (BeansException var26) {
                    this.cleanupAfterBeanCreationFailure(beanName);
                    throw var26;
                }
            }
           // 如果類型不為空,beanName不存在也就是沒有拿到本地的bean
            if (requiredType != null && !requiredType.isInstance(bean)) {
                try {
          //調用類型轉換器進行bean的轉換
                    T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
                    如果轉換后的bean還是為空
            if (convertedBean == null) {
            //拋出bean類型異常
                        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            //        直接返回轉換后的bean
            } else {
                        return convertedBean;
                    }
          //拋出類型匹配異常
                } catch (TypeMismatchException var25) {
          //調用日志類進行記錄
                    if (this.logger.isTraceEnabled()) {
          //  寫入日志信息
                        this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
                    }
    
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
            } else {
                return bean;
            }
        }
    
    


免責聲明!

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



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