1. 程式人生 > 其它 >Spring原始碼分析系列——bean建立過程分析(二)——有參構造方法建立bean

Spring原始碼分析系列——bean建立過程分析(二)——有參構造方法建立bean

技術標籤:原始碼springspringjava

前言

spring建立bean的方式

  1. 構造方法
    1. 無參構造方法
    2. 有參構造方法
  2. 工廠方法
    1. 靜態工廠方法
    2. 例項工廠方法
  3. 實現FactoryBean介面

上一篇《Spring原始碼分析系列——bean建立過程分析(一)——預設無參構造方法建立bean》分析了預設無參構造方法建立bean的方式,本篇分析有參構造方法建立bean。和無參構造方法建立bean的主流程一致,都是經getBean、doGetBean、createBean、doCreateBean、createBeanInstance等步驟,本次直接從createBeanInstance方法開始分析

createBeanInstance()方法分析

精簡後的程式碼,關鍵步驟已添加註釋

protected
BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); //如果有工廠方法,則走工廠方法建立bean if (mbd.getFactoryMethodName() != null) { return
instantiateUsingFactoryMethod(beanName, mbd, args); } //檢視快取的資料(第一次解析構造方法或者工廠方法後會快取相應資料) //resolved表示是否之前已經解析過構造方法或者工廠方法, //autowireNecessary 表示是否有autowire註解的構造方法 boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } //解析過 if (resolved) { //有autowire註解的構造方法 if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } //預設的無參構造方法 else { return instantiateBean(beanName, mbd); } } //所有標註autowire註解的構造方法 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //如果有autowire註解的構造方法,則走這種方式 return autowireConstructor(beanName, mbd, ctors, args); } // 走無參構造方法建立 return instantiateBean(beanName, mbd); }

autowireConstructor()方法分析

protected BeanWrapper autowireConstructor(
			String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

		return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
	}

委託給ConstructorResolver處理,程式碼很長,邏輯也比較賦值,我們抽出主幹

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();		
		
		//要採用的constructor和args等變數
		Constructor<?> constructorToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		//從快取中獲取constructor和args,第一次的時候是沒有的
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
			}
		}

		if (constructorToUse == null || argsToUse == null) {
			// Take specified constructors, if any.
			Constructor<?>[] candidates = chosenCtors;
			
			//這裡多了一個優化,就是當候選的costructor就只有一個的時候判斷一下是否是無參構造方法,如果是就直接走無參構造方法建立bean了
			if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Constructor<?> uniqueCandidate = candidates[0];
				if (uniqueCandidate.getParameterCount() == 0) {
					synchronized (mbd.constructorArgumentLock) {
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			// 需要開始解析構造方法了
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}
			
			//按照構造方法引數數量從大到小排列,儘量選擇引數值最多的構造方法建立bean
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			LinkedList<UnsatisfiedDependencyException> causes = null;
			
			//遍歷候選構造方法,找到最終需要的constructor和args
			for (Constructor<?> candidate : candidates) {
				//構造方法引數數量
				int parameterCount = candidate.getParameterCount();
				
				//如果已經找到,則退出迴圈
				if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
					break;
				}
				if (parameterCount < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
				Class<?>[] paramTypes = candidate.getParameterTypes();
				if (resolvedValues != null) {
					try {
						//引數的名稱,一般不走
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
						if (paramNames == null) {
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							//真正獲取引數的名稱
							if (pnd != null) {
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						//構造方法引數賦值,重要方法!!!
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
					}
					catch (UnsatisfiedDependencyException ex) {
						
					}
				}
				else {
					// Explicit arguments given -> arguments length must match exactly.
					if (parameterCount != explicitArgs.length) {
						continue;
					}
					argsHolder = new ArgumentsHolder(explicitArgs);
				}

				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
						
				// 選擇這個構造方法,並賦值
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}				
			}

			//把找到的構造方法和引數值放入mbd快取
			if (explicitArgs == null && argsHolderToUse != null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}
		
		//根據找到的構造方法和引數值反射建立bean
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}

這裡還有一個重要的方法createArgumentArray,實現構造方法引數賦值,來看一下

構造方法引數賦值createArgumentArray()方法解析

精簡後代碼

private ArgumentsHolder createArgumentArray(
			String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
			BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
			boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {

		TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
		TypeConverter converter = (customConverter != null ? customConverter : bw);
		
		//ArgumentsHolder是引數封裝
		ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
		Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		
		//依次對引數解析
		for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
			Class<?> paramType = paramTypes[paramIndex];
			String paramName = (paramNames != null ? paramNames[paramIndex] : "");
			// Try to find matching constructor argument value, either indexed or generic.
			ConstructorArgumentValues.ValueHolder valueHolder = null;
			if (resolvedValues != null) {
				//解析快取的引數值
				valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
				// If we couldn't find a direct match and are not supposed to autowire,
				// let's try the next generic, untyped argument value as fallback:
				// it could match after type conversion (for example, String -> int).
				if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
					valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
				}
			}
			//第一次快取沒有,valueHolder==null,所以不走這裡
			if (valueHolder != null) {				
				usedValueHolders.add(valueHolder);
				Object originalValue = valueHolder.getValue();
				Object convertedValue;
				if (valueHolder.isConverted()) {
					convertedValue = valueHolder.getConvertedValue();
					args.preparedArguments[paramIndex] = convertedValue;
				}
				else {
					MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
					try {
						convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
					}
					catch (TypeMismatchException ex) {
						throw new UnsatisfiedDependencyException(
								mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
								"Could not convert argument value of type [" +
										ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
										"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
					}
					Object sourceHolder = valueHolder.getSource();
					if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
						Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
						args.resolveNecessary = true;
						args.preparedArguments[paramIndex] = sourceValue;
					}
				}
				args.arguments[paramIndex] = convertedValue;
				args.rawArguments[paramIndex] = originalValue;
			}
			//第一次沒有快取,走這裡
			else {
				//MethodParameter是對形參的封裝
				MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
				
				//解析自動裝配的引數值,並賦值給args
				try {
					Object autowiredArgument = resolveAutowiredArgument(
							methodParam, beanName, autowiredBeanNames, converter, fallback);
					args.rawArguments[paramIndex] = autowiredArgument;
					args.arguments[paramIndex] = autowiredArgument;
					args.preparedArguments[paramIndex] = autowiredArgumentMarker;
					args.resolveNecessary = true;
				}
				catch (BeansException ex) {
					
				}
			}
		}
		

		return args;
	}

resolveAutowiredArgument()方法實現引數自動裝配

程式碼精簡後

protected Object resolveAutowiredArgument(MethodParameter param, String beanName,
			@Nullable Set<String> autowiredBeanNames, TypeConverter typeConverter, boolean fallback) {

		
			return this.beanFactory.resolveDependency(
					new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
		
	}

這裡的DependencyDescriptor是對形參的進一步封裝
看一下DefaultListableBeanFactory裡的resolveDependency方法

DefaultListableBeanFactory裡resolveDependency()方法解析

程式碼精簡後

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		Object result = 
			doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			
		return result;
	}

看下 doResolveDependency()方法

DefaultListableBeanFactory裡doResolveDependency()方法解析

程式碼精簡後

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		try {
			

			Class<?> type = descriptor.getDependencyType();
			//獲取@value註解的自動注入引數值
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					//value如果不是string型別,比如int等,需要轉換一下
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					
				}
			}
			
			//對Map、Array、list等集合型別引數解析
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
		
			//對普通bean的形參型別賦值
			//根據class型別查詢bean,返回的matchingBeans key是例項的beanName,value是class			
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				
			}
			else {
				//只有一個合適的bean
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			//如果是class,則從bean工廠獲得bean例項
			if (instanceCandidate instanceof Class) {
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			
			return result;
		}
		
	}

簡單看一下descriptor的resolveCandidate方法

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
			throws BeansException {

		return beanFactory.getBean(beanName);
	}

一目瞭然,通過getBean從bean工廠獲取bean

總結

本文用最通常的方式解析了有參構造方法建立bean(同時必須對形參賦值),省略了大量分支情況程式碼,只為了使主幹清晰,有興趣的朋友可以根據主幹閱讀省略的分支程式碼。