spring构造函数依赖注入

提问:

1、三个构造器(含有无参构造器,且没有@Autowired注解,Spring总是使用无参构造器实例化Bean。

2、一个有参构造器,并且没有@Autowired注解,Spring将会使用该构造器注入Bean的方式初始化Bean。

3、三个构造器,有一个构造器上打上**@Autowired注解,可以正常注入构造器。有两个@Autowired注解就会报错**,多个@Autowired需要在所有@Autowired中的required都加上false才可正常初始化。

spring实例化时,选择构造器的逻辑如下:
1、在没有@Autowired注解的情况下:

无参构造器将直接加入defaultConstructor集合中。

在构造器数量只有一个且有参数时,此唯一有参构造器将加入candidateConstructors集合中。

在构造器数量有两个的时候,并且存在无参构造器,将defaultConstructor(第一条的无参构造器)放入candidateConstructors集合中。

在构造器数量大于两个,且无论是否存在无参构造器的情况下,将返回一个空的candidateConstructors集合,
也就是没有找到构造器(这种情况后续会使用class.getConstructor()默认无参构造器实例化bean)。


总结:spring也不是傻子,有且只有一个构造函数时,无论是否有参,都选这个构造函数。

当构造函数有两个或以上时,会选择无参构造函数。如果没有无参构造函数,则报错(抛出的

是java的异常,没有无参构造函数时,spring最终会调用class.getConstructor(),无参,

所以会抛找不到这个方法的异常)。



2、在有@Autowired注解的情况下:

判断required属性:
true:先判断requiredConstructor集合是否为空,若不为空则代表之前已经有一个
required=true的构造器了,两个true将抛出异常,再判断candidates集合是否为空,
若不为空则表示之前已经有一个打了注解的构造器,此时required又是true,抛出异常。
若两者都不为空将放入requiredConstructor集合中,再放入candidates集合中。

false:直接放入candidates集合中。
判断requiredConstructor集合是否为空(是否存在required=true的构造器),若没有,
将默认构造器也放入candidates集合中。

最后将上述candidates赋值给最终返回的candidateConstructors集合。


总结:当有required=true时,如果只有一个 @Autowired注解,则使用这个构造函数。

如果有多个@Autowired注解,直接抛异常。当 所有@Autowired注解都是require = false时,

这些构造函数的地位和无参构造函数一样,最终会被收集到合适的构造函数列表里。

然后会有一个排序,最终在构造函数列表里挑选参数长的构造器来实例化bean。
源码如下:

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

    //略..

	// Quick check on the concurrent map first, with minimal locking.
		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		if (candidateConstructors == null) {
			// Fully synchronized resolution now...
			synchronized (this.candidateConstructorsCache) {
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				if (candidateConstructors == null) {
					Constructor<?>[] rawCandidates;
					try {
						// 获取bean对应的所有构造器
						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的构造器
					Constructor<?> requiredConstructor = null;
					// 存放默认构造器
					Constructor<?> defaultConstructor = null;
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					int nonSyntheticConstructors = 0;
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
						// 如果构造器上没有注解(@Autowired 注解)
						if (ann == null) {
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						// 如果构造器上包含 @Autowired注解
						if (ann != null) {
							// 已经存在一个required=true的构造器了,抛出异常
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							// 判断此注解上的required属性
							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);
								}
								// 赋值当前构造器到  依赖注入的required=true的对象
								requiredConstructor = candidate;
							}
							// 加入适用的构造器集合中
							candidates.add(candidate);
						}
						else if (candidate.getParameterCount() == 0) {
							// 赋值当前构造器到  默认构造器对象
							defaultConstructor = candidate;
						}
					}
					// 正常情况下,只有 @Autowired注解注解的构造器才能加入到  candidates  中
					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						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]);
					}
					// 如果不包含 @Autowired注解 且只有一个有参构造函数,返回这个构造函数
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
					// 如果构造器有两个,且默认构造器不为空
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}

					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					// 上述都不符合的话,只能返回一个空集合了
					else {
						candidateConstructors = new Constructor<?>[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
}