spring5源码篇(6)——bean的依赖注入之构造器注入

文章详细阐述了SpringFramework在创建bean实例时的过程,包括通过`createBeanInstance`方法选择构造方法,利用`determineConstructorsFromBeanPostProcessors`推断构造方法,以及`autowireConstructor`进行参数注入。文章重点讨论了如何处理@Autowired注解、构造方法的选择策略和参数解析,展示了Spring如何处理bean实例化时的构造方法选择和依赖注入。
摘要由CSDN通过智能技术生成

spring-framework 版本:v5.3.19

话不多说直接上代码

createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		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());
		}

		//配置的supplier创建bean
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		//配置的工厂方法(factory-method)创建bean(如:@Bean注解)
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		//之前是否已经处理过
		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);
		// 有推断构造方法 || autowire模式 || mbd中有指定构造参数 || 运行时有参数传入
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// 使用特定配置的构造方法(一般情况下返回null)
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// 默认无参构造
		return instantiateBean(beanName, mbd);
	}

determineConstructorsFromBeanPostProcessors 推断构造方法

在这里插入图片描述
AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
			throws BeanCreationException {

		// @lookUp注解的处理
		if (!this.lookupMethodsChecked.contains(beanName)) {
			if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
				try {
					Class<?> targetClass = beanClass;
					do {
						ReflectionUtils.doWithLocalMethods(targetClass, method -> {
							Lookup lookup = method.getAnnotation(Lookup.class);
							if (lookup != null) {
								Assert.state(this.beanFactory != null, "No BeanFactory available");
								LookupOverride override = new LookupOverride(method, lookup.value());
								try {
									RootBeanDefinition mbd = (RootBeanDefinition)
											this.beanFactory.getMergedBeanDefinition(beanName);
									mbd.getMethodOverrides().addOverride(override);
								}
								catch (NoSuchBeanDefinitionException ex) {
									throw new BeanCreationException(beanName,
											"Cannot apply @Lookup to beans without corresponding bean definition");
								}
							}
						});
						targetClass = targetClass.getSuperclass();
					}
					while (targetClass != null && targetClass != Object.class);

				}
				catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
				}
			}
			this.lookupMethodsChecked.add(beanName);
		}

		// 先检查缓存
 		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		if (candidateConstructors == null) {
			synchronized (this.candidateConstructorsCache) {
				//双重判断,再次检查缓存,缓存中没有就推断
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				if (candidateConstructors == null) {
					Constructor<?>[] rawCandidates;
					try {
						//先获取所有构造方法
						rawCandidates = beanClass.getDeclaredConstructors();
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName,
								"Resolution of declared constructors on bean Class [" + beanClass.getName() +
								"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
					}
					//匹配到合适的构造器集合
					List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
					//被标记为required=true的构造(这里可以看出只能有一个true)
					Constructor<?> requiredConstructor = null;
					//默认构造
					Constructor<?> defaultConstructor = null;
					//Kotlin相关的(java开发一般不会用。不用管)
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					//记录合成的构造方法数量(java开发一般不会用。不用管)
					int nonSyntheticConstructors = 0;
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
						//寻找@Autowire注解
						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
						if (ann == null) {
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									// 在父类中找@Autowired的构造方法
									Constructor<?> superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						//如果有@Autowire注解,将其加入合适的构造器列表中
						if (ann != null) {
							//如果发现存在required=true且有多个@autowire就报错
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							boolean required = determineRequiredStatus(ann);
							if (required) {
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								requiredConstructor = candidate;
							}
							candidates.add(candidate);
						}
						//如果没有@Autowire注解且参数个数0,说明这是默认构造
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
					//如果@autowire匹配的不为空,且没有required且存在默认构造则添加 默认构造 返回
					if (!candidates.isEmpty()) {
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
							else if (candidates.size() == 1 && logger.isInfoEnabled()) {
								logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
										"': single autowire-marked constructor flagged as optional - " +
										"this constructor is effectively required since there is no " +
										"default constructor to fall back to: " + candidates.get(0));
							}
						}
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
					//只有1个构造方法且参数大于0返回这个构造器
					// 这种情况返回值不为空createBeanInstance就会走autowireConstructor且会开启自动注入模式
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
					// primaryConstructor java开发一般都是null
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}
					// primaryConstructor java开发一般都是null
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					//上诉都不符合返回null
					else {
						candidateConstructors = new Constructor<?>[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}
  1. 找出所有@Autowired注解构造方法(包括父类)
  2. 如果有@Autowire且存在默认构造则添加默认构造返回
  3. 如果只有一个构造方法且有参则返回这个构造
  4. 反之返回null用默认构造

autowireConstructor 选择构造方法并注入参数

在这里插入图片描述
ConstructorResolver#autowireConstructor

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

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);

		//使用的构造方法
		Constructor<?> constructorToUse = null;
		//使用的参数封装
		ArgumentsHolder argsHolderToUse = null;
		//使用的参数
		Object[] argsToUse = null;

		//先从运行传入参数或者缓存找使用构造方法和使用参数
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						//原始参数
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				//转化参数(如提供参数是RuntimeBeanNameReference("beanName")就会转化成spring中的bean)
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}

		//如果没有使用构造或使用参数则自动寻找
		if (constructorToUse == null || argsToUse == null) {
			//如果没有传入可选构造方法,则在所有的构造方法中选
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Resolution of declared constructors on bean Class [" + beanClass.getName() +
							"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
				}
			}

			//如果只有一个候选构造且无参数且没有传递参数则用该构造
			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;
				}
			}

			//当chosenCtors不为空(有autowire注解或者只有一个有参构造方法)或者指定了constructor模式就表示开启自动注入
			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);
			}

			//遍历构造方法顺序排序  public排前面 -》参数个数多排前面
			AutowireUtils.sortConstructors(candidates);
			//构造方法得分(分数越小优先级越高)
			int minTypeDiffWeight = Integer.MAX_VALUE;
			//合适的构造方法
			Set<Constructor<?>> ambiguousConstructors = null;
			Deque<UnsatisfiedDependencyException> causes = null;

			for (Constructor<?> candidate : candidates) {
				int parameterCount = candidate.getParameterCount();

				//已经找到合适的话,只最后遍历后面相同访问级别,相同参数个数的构造后就不再考虑其他构造方法
				if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
					break;
				}
				//如果参数个数小于最小值则continue
				if (parameterCount < minNrOfArgs) {
					continue;
				}

				//封装参数
				ArgumentsHolder argsHolder;
				Class<?>[] paramTypes = candidate.getParameterTypes();
				// resolvedValues!=null 说明没有传入构造参数,则交由spring注入
				if (resolvedValues != null) {
					try {
						//@ConstructorProperties注解的处理
						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) {
						if (logger.isTraceEnabled()) {
							logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next constructor.
						if (causes == null) {
							causes = new ArrayDeque<>(1);
						}
						causes.add(ex);
						continue;
					}
				}
				//传入构造参数则个数必须匹配
				else {
					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;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					//如果得分相同则加入 ambiguousConstructors(表示这里“摸棱两可”,至于要不要报错由lenientConstructorResolution决定)
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}

			//没有匹配到合适的构造则报错
			if (constructorToUse == null) {
				if (causes != null) {
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
			}
			//ambiguousConstructors不为空且不是 宽松模式 则报错
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}

			//缓存此次结果
			if (explicitArgs == null && argsHolderToUse != null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		//有参实例化
		Assert.state(argsToUse != null, "Unresolved constructor arguments");
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}

遍历推断出的构造方法,为其注入参数并计算优先级,最高优先级的那个则为最终使用的构造方法。

  1. 如果只有一个候选构造且无参数且没有传递参数则用该构造
  2. 排序构造方法并遍历计算得分得到优先级(public排前面 -> 参数个数多排前面)
    a. 如果已经找到合适的,只最后遍历后面相同访问级别,相同参数个数的构造后就不再考虑其他构造方法
    b. 如果参数个数小于最小值则continue
    c. 如果构造方法有手动传入参数则只考虑相同参数个数的构造方法,反之填充构造参数(构造器自动注入就在这一步)
    d. 根据参数类型去计算得分,得分越小优先级越高。(计算得分有两种模式 宽松模式:原始参数和转化后的参数只取数值小的那一个 严格模式:原始参数和转化后的参数都参与计算两个结果叠加)
  3. 如果没有匹配到就报错,反之最高优先级找到多个就根据是否宽松模式来决定是用第一个还是抛异常

至于构造器参数是怎么自动注入的我就不细究了,其实和上篇setter,field注入一样,最终都会调用DefaultListableBeanFactory#resolveDependency去寻找合适的bean注入。

其实这里一开始我有个疑问,就是第一步"如果只有一个候选构造且无参数且没有传递参数则用该构造"那不就是无参构造嘛,无参构造为什么还会进到这个方法,不应该在推断的时候返回null,然后执行instantiateBean吗。确实一般情况下,无参构造都会走到那。我能想到的场景就是在无参构造上加@Autowired。

是否宽松模式由mbd.isLenientConstructorResolution指定

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值