1. 程式人生 > >【Spring原始碼閱讀】populateBean實現 依賴注入原始碼解析

【Spring原始碼閱讀】populateBean實現 依賴注入原始碼解析

在完成Bean例項化後,Spring容器會給這個Bean注入相關的依賴Bean,在原始碼中,這一步通過類AbstractAutowireCapableBeanFactory中的populateBean方法完成。

測試程式碼

下面開始進入原始碼分析之前,先基於以下例項進行:

// 基礎屬性類
public class Student {

    private String name;

    public Student(String name) {
        this.name = name;
    }

    public String getName()
{ return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [name=" + name + "]"; } } // 需要進行依賴注入的類 public class TestBean { private Student student; public void echo() { System.
out.println("I'm a student : " + student); } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } }

配置程式碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="com.jeanheo.model.Student" id="student"> <constructor-arg index="0" value="test"/> </bean> <bean class="com.jeanheo.model.TestBean2" id="testBean"> <property name="student" ref="student"/> </bean> </beans>

具體測試程式碼:

public class BaseTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
        TestBean testBean = context.getBean("testBean", TestBean.class);
        testBean.echo();
    }
}

原始碼分析

下面基於TestBean的依賴注入進行分析相關原始碼:

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    // pvs是一個MutablePropertyValues例項,裡面實現了PropertyValues介面,提供屬性的讀寫操作實現,同時可以通過呼叫建構函式實現深拷貝
    // 在本例中,裡面存在一個propertyValueList,裡面只有一個propertyValue:key->value="student"->RuntimeBeanReference("<student>")
	PropertyValues pvs = mbd.getPropertyValues();

	if (bw == null) {
		if (!pvs.isEmpty()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		else {
			// 空物件直接返回
			return;
		}
	}

	// 給InstantiationAwareBeanPostProcessors最後一次機會在屬性注入前修改Bean的屬性值
	// 具體通過呼叫postProcessAfterInstantiation方法,如果呼叫返回false,表示不必繼續進行依賴注入,直接返回
	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;
	}

    // 根據Bean配置的依賴注入方式完成注入,預設是0,即不走以下邏輯,所有的依賴注入都需要在xml檔案中有顯式的配置
    // 如果設定了相關的依賴裝配方式,會遍歷Bean中的屬性,根據型別或名稱來完成相應注入,無需額外配置
	if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
		// 深拷貝當前已有的配置
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

		// 根據名稱進行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}

		// // 根據型別進行注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}
        // 結合注入後的配置,覆蓋當前配置
		pvs = newPvs;
	}
    
    // 容器是否註冊了InstantiationAwareBeanPostProcessor
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	// 是否進行依賴檢查
	boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
	if (hasInstAwareBpps || needsDepCheck) {
	    // 過濾出所有需要進行依賴檢查的屬性編輯器
		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		if (hasInstAwareBpps) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
			    // 如果有相關的後置處理器,進行後置處理
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return;
					}
				}
			}
		}
		if (needsDepCheck) {
		    // 檢查是否滿足相關依賴關係,對應的depends-on屬性,需要確保所有依賴的Bean先完成初始化
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}
	}
    // 將pvs上所有的屬性填充到BeanWrapper對應的Bean例項中,注意到這一步,TestBean的student屬性還是RuntimeBeanReference,即還未解析實際的Student例項
	applyPropertyValues(beanName, mbd, bw, pvs);
}

在具體分析原始碼如何將將pvs上所有的屬性填充到BeanWrapper對應的Bean例項中之前,先看看autowireByName和autowireByType這兩步是怎麼實現的:

protected void autowireByName(
		String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    // 根據bw的PropertyDescriptors,遍歷出所有可寫的(即set方法存在),存在於BeanDefinition裡的PropertyValues,且不是簡單屬性的屬性名
    // 簡單屬性的判定參照下面方法,主要涵蓋基本型別及其包裝類,Number,Date等
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		if (containsBean(propertyName)) {
		    // 遞迴初始化相關Bean
			Object bean = getBean(propertyName);
			// 根據名稱新增到pvs中
			pvs.add(propertyName, bean);
			// 註冊依賴關係
			registerDependentBean(propertyName, beanName);
			if (logger.isDebugEnabled()) {
				logger.debug("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");
			}
		}
	}
}

// 簡單型別判定
public static boolean isSimpleValueType(Class<?> clazz) {
	return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||
			CharSequence.class.isAssignableFrom(clazz) ||
			Number.class.isAssignableFrom(clazz) ||
			Date.class.isAssignableFrom(clazz) ||
			clazz.equals(URI.class) || clazz.equals(URL.class) ||
			clazz.equals(Locale.class) || clazz.equals(Class.class);
}

類似的,下面再看看autowireByType的實現

protected void autowireByType(
		String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    // 獲取型別轉換器
	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
		converter = bw;
	}

	Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
	// 類似的,過濾出滿足裝配條件的Bean屬性
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		try {
			如果是Object型別不進行裝配
			if (!Object.class.equals(pd.getPropertyType())) {
			    // 獲取相關的寫方法引數
				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
				// 定義是否允許懶載入。
				boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
			    // 
				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
				// 這裡會根據傳入desc裡的入參型別,作為依賴裝配的型別
				// 再根據這個型別在BeanFacoty中查詢所有類或其父類相同的BeanName
				// 最後根據BeanName獲取或初始化相應的類,然後將所有滿足條件的BeanName填充到autowiredBeanNames中。
				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
				if (autowiredArgument != null) {
					pvs.add(propertyName, autowiredArgument);
				}
				for (String autowiredBeanName : autowiredBeanNames) {
				    // 註冊依賴
					registerDependentBean(autowiredBeanName, beanName);
					if (logger.isDebugEnabled()) {
						logger.debug("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);
		}
	}
}

具體pvs上所有的屬性填充到BeanWrapper對應的Bean例項中實現如下:

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    // 為空直接返回
	if (pvs == null || pvs.isEmpty()) {
		return;
	}

	MutablePropertyValues mpvs = null;
	List<PropertyValue> original;

	if (System.getSecurityManager() != null) {
		if (bw instanceof BeanWrapperImpl) {
			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
		}
	}

	if (pvs instanceof MutablePropertyValues) {
		mpvs = (MutablePropertyValues) pvs;
		if (mpvs.isConverted()) {
			// 如果已被設定轉換完成,直接完成配置
			try {
				bw.setPropertyValues(mpvs);
				return;
			}
			catch (BeansException ex) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Error setting property values", ex);
			}
		}
		original = mpvs.getPropertyValueList();
	}
	else {
		original = Arrays.asList(pvs.getPropertyValues());
	}
    
	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
		converter = bw;
	}
	// 建立BeanDefinitionValueResolver解析器,用來解析未被解析的PropertyValue。
	BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

	// 開始遍歷檢查original中的屬性,對未被解析的先解析/已解析的直接加入deepCopy中,最後再填充到具體的Bean例項中
	List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
	boolean resolveNecessary = false;
	for (PropertyValue pv : original) {
	    // 如果屬性已經轉化,直接新增
		if (pv.isConverted()) {
			deepCopy.add(pv);
		}
		else {
			String propertyName = pv.getName();
			Object originalValue = pv.getValue();
			// 核心邏輯,解析獲取實際的值
			// 對於RuntimeReference,會解析拿到具體的beanName,最終通過getBean(beanName)拿到具體的物件
			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
			Object convertedValue = resolvedValue;
			// 判斷是否可以轉換
			boolean convertible = bw.isWritableProperty(propertyName) &&
					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
			if (convertible) {
			    // 嘗試進行轉換
				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
			}
			// 避免需要重複轉換,設定已轉換
			if (resolvedValue == originalValue) {
				if (convertible) {
					pv.setConvertedValue(convertedValue);
				}
				deepCopy.add(pv);
			}
			else if (convertible && originalValue instanceof TypedStringValue &&
					!((TypedStringValue) originalValue).isDynamic() &&
					!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
				pv.setConvertedValue(convertedValue);
				deepCopy.add(pv);
			}
			else {
				resolveNecessary = true;
				deepCopy.add(new PropertyValue(pv, convertedValue));
			}
		}
	}
	if (mpvs != null && !resolveNecessary) {
		mpvs.setConverted();
	}

	// 完成設定
	try {
		bw.setPropertyValues(new MutablePropertyValues(deepCopy));
	}
	catch (BeansException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
	}
}

上面大致的描述了Spring完成依賴注入的流程,中間具體還有很多細緻的複雜處理細節,但通過上述的原始碼解讀,我們大致瞭解了整個Spring容器的依賴注入實現基礎流程。