bean的創建過程

bean的創建過程

1.入口

這個是接着bean的加載過程進行分析

return createBean(beanName, mbd, args);

2.使用bean的定義mbd和傳入參數beanName來獲取class,這塊可以參考一下AbstractBeanDefinition,這個對象中提供了獲取class的方法getBeanClass(),完成參數的設置。

Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

3.這個方法就是獲取該方法下所有overied方法,然後獲取所有的接口和父類的方法,如果方法名大於1的該方法的overloaded屬性就是true,進行記錄。

mbdToUse.prepareMethodOverrides();

4.實例化前後處理程序已啓動 對beanDefinition的一些參數進行處理

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

上面4步可以總結爲就是對該beanDefnition的一些預處理操作:如覆蓋方法的屬性標誌,創建實例化前處理器屬性的標誌。

5.進行實際創建步驟

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

6.首先是要從緩存中進行獲取

// 實例化bean。
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			//未完成FactoryBean實例的緩存:將FactoryBean名稱緩存到BeanWrapper{清除緩存}
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}

這裏面要解釋一下BeanWrapper{Spring底層javabean基礎設施的核心接口。 }

7.實例化一個bean的實例,實例化bean的實例基本上有三種方式:

第一種:使用該bean的工廠

第二種:帶有參數的構造方法{這個比較麻煩,需要進行參數的解析和構造函數的解析和匹配}

第三種:默認參數的構造

/**
	 * 使用適當的實例化策略爲指定的bean創建一個新實例:
	 * 工廠方法、構造函數自動連接或簡單實例化。
	 * @param beanName bean的名字
	 * @param mbd bean的定義
	 * @param args 用於構造函數或工廠方法調用的顯式參數
	 * @return 新實例的BeanWrapper
	 * @see #obtainFromSupplier
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 * @see #instantiateBean
	 */
	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 確保bean類在這一點上得到了實際的解析。解析beanName獲取到beanClass
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		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());
		}
		//獲取bean創建的回調如果有的話
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		//如果工廠方式不爲空則用工廠方式創建
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// 重新創建相同bean時的快捷方式…
		boolean resolved = false;
		boolean autowireNecessary = false;
		//進行參數解析
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				// 一個類有多個構造函數,每個構造函數都有不同的參數,所以調用前需要先根據參數鎖定構造函數或對應的工廠方法
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		//如果已經解析過則使用解析好的構造函數方法不需要再次鎖定
		if (resolved) {
			if (autowireNecessary) {
				//參數構造解析方式
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				//默認解析方式
				return instantiateBean(beanName, mbd);
			}
		}

		// 解析構造參數
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			//構造函數自動注入
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// 無需特殊處理:只需使用無參數構造函數。
		return instantiateBean(beanName, mbd);
	}

8.合併bean的定義

synchronized (mbd.postProcessingLock) {
   if (!mbd.postProcessed) {
      try {
         //將MergedBeanDefinitionPostProcessors應用於指定的bean定義
         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      }
      catch (Throwable ex) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Post-processing of merged bean definition failed", ex);
      }
      mbd.postProcessed = true;
   }
}

9.是否添加到單例工廠

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

10.屬性的注入,分爲兩種,一種是按名稱注入,一種是按類型注入

populateBean(beanName, mbd, instanceWrapper);

①按名稱注入

/**
 * 在傳入的參數中找到該bean並實例化初始化屬性參數
 * 用引用填充任何缺失的屬性值
 * *如果autowire設置爲“byName”,則此工廠中的其他bean。
 * @param beanName 我們正在連接的bean的名稱。
 * Useful for debugging messages; not used functionally.
 * @param mbd 通過自動連接更新bean定義
 * @param bw 我們可以從中獲取關於bean的信息的bean包裝器
 * @param pvs 用於註冊連接對象的PropertyValues
 */
protected void autowireByName(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
      if (containsBean(propertyName)) {
         Object bean = getBean(propertyName);
         pvs.add(propertyName, bean);
         registerDependentBean(propertyName, beanName);
         if (logger.isTraceEnabled()) {
            logger.trace("Added autowiring by name from bean name '" + beanName +
                  "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
         }
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                  "' by name: no matching bean found");
         }
      }
   }
}

②按類型注入

/**
 * 抽象方法定義“按類型自動連接”(按類型定義bean屬性)行爲。
 * 這類似於PicoContainer默認值,其中必須只有一個bean
 * *表示bean工廠中的屬性類型。這使得bean工廠非常簡單
 * *配置小的名稱空間,但不能像標準Spring那樣工作
 * *大型應用程序的行爲。
 * @param beanName the name of the bean to autowire by type
 * @param mbd the merged bean definition to update through autowiring
 * @param bw the BeanWrapper from which we can obtain information about the bean
 * @param pvs the PropertyValues to register wired objects with
 */
protected void autowireByType(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }

   Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
   //尋找bw中需要進行依賴注入的屬性
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
      try {
         PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
         // Don't try autowiring by type for type Object: never makes sense,
         // even if it technically is a unsatisfied, non-simple property.
         if (Object.class != pd.getPropertyType()) {
            //探測指定屬性的set方法
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
            // 在優先級後處理器的情況下,不允許立即初始化進行類型匹配。
            boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
            DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
            Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
            // 解析指定 beanName 的屬性所匹配的值,並把解析到的屬性名稱存儲在
            // autowireBeanNames 中,當屬性存在多個封裝 bean 時,如:
            // @Autowired private List<A> aList; 將會找到所有匹配 A 類型
            // 的 bean 並將其注入
            if (autowiredArgument != null) {
               //將bean中屬性匹配類型添加進去
               pvs.add(propertyName, autowiredArgument);
            }
            for (String autowiredBeanName : autowiredBeanNames) {
               //註冊依賴
               registerDependentBean(autowiredBeanName, beanName);
               if (logger.isTraceEnabled()) {
                  logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                        propertyName + "' to bean named '" + autowiredBeanName + "'");
               }
            }
            autowiredBeanNames.clear();
         }
      }
      catch (BeansException ex) {
         throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
      }
   }
}

①根據名稱注入,首先獲取該bean所需要進行注入的所有屬性

然後根據getBean方法循環遞歸實例化並加入到pvs中

②根據類型注入,首先獲取該bean所需要進行注入的所有屬性

然後循環獲取每個屬性的解釋器

然後根據解釋器探測每個屬性的setter方法

解析指定 beanName 的屬性所匹配的值,並把解析到的屬性名稱存儲在autowireBeanNames,並加入到pvs中

最終會設置到beanWapper的properties參數中去。

11.bean的創建,這個過程會有初始化方法和一些後處理器的作用

exposedObject = initializeBean(beanName, exposedObject, mbd);

12.如果該bean存在早起的應用需要進行依賴的檢測

if (earlySingletonExposure) {
   Object earlySingletonReference = getSingleton(beanName, false);
   if (earlySingletonReference != null) {
      //如果該bean沒有被增強
      if (exposedObject == bean) {
         exposedObject = earlySingletonReference;
      }
      //如果沒增強,則獲取它所有的依賴處理
      //在循環引用時是否採用注入生bean實例;確定是否爲給定名稱註冊了依賴bean
      //不允許注入原生的bean,併爲給定名稱註冊依賴bean
      //進行的則是依賴檢測
      else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
         String[] dependentBeans = getDependentBeans(beanName);
         Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
         for (String dependentBean : dependentBeans) {
            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
               actualDependentBeans.add(dependentBean);
            }
         }
         if (!actualDependentBeans.isEmpty()) {
            throw new BeanCurrentlyInCreationException(beanName,
                  "Bean with name '" + beanName + "' has been injected into other beans [" +
                  StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                  "] in its raw version as part of a circular reference, but has eventually been " +
                  "wrapped. This means that said other beans do not use the final version of the " +
                  "bean. This is often the result of over-eager type matching - consider using " +
                  "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
         }
      }
   }
}

13.就是將disposableBeans添加一個記錄

// 將bean按照scope進行註冊
try {
   registerDisposableBeanIfNecessary(beanName, bean, mbd);
}

/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章