• spring5.3 十:推断构造方法源码分析


    推断构造方法源码分析

    Spring中的一个bean,需要实例化得到一个对象时需要用到构造方法。一般情况下,一个类只有一个构造方法:
    要么是无参的构造方法,要么是有参的构造方法。
    如果只有一个无参的构造方法,那么实例化就只能使用这个构造方法了。
    如果只有一个有参的构造方法,那么实例化时用这个构造方法的入参类型去找BeanFactory有没有符合的参数,没有的话会报错。
    如果有多个构造方法呢?这就要分两种情况。

    1. 如果存在无参构造,默认使用无参构造
    2. 不存在无参构造,则会报错 Failed to instantiate [service.OrderServiceImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: service.OrderServiceImpl.()

    那么如何解决上述的错误呢,或者有多个构造方法我想指定使用哪个怎么做呢?
    可以在构造方法上加上@Autowired注解。告诉spring使用哪个构造方法,或者通过BeanDefinition设置使用的构造方法。

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    		context.register(AppConfig.class);
    		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
    		//确定beanDefinition的类型
    		beanDefinition.setBeanClass(OrderServiceImpl.class);
    		//构造方法参数赋值
    		beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new UserServiceImpl());
    		//自动注入模式 目的是让spring 帮我们找构造方法和参数 如果不设置,spring根据入参个数来找构造方法
    		beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    		//将beanDefinition放入到spring容器中
    		context.registerBeanDefinition("orderServiceImpl",beanDefinition);
    		context.refresh();
    		OrderServiceImpl OrderServiceImpl = context.getBean("orderServiceImpl", OrderServiceImpl.class);
    		OrderServiceImpl.test();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    源码分析

    上面大概叙述了spring构造方法的选择的情况。接下来根据上述的情况分析spring推断构造方法的源码。推断构造方法的过程在spring生命周期中的实例化阶段。也就是doCreateBean中的instanceWrapper = createBeanInstance(beanName, mbd, args);这行代码中

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    		//Object[] args 表示通过getBean方法 传进来的 构造方法入参
    		// Make sure bean class is actually resolved at this point.
    		//根据RootBeanDefinition 和beanName 获取类对象
    		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());
    		}
    		// 如果BeanDefinition中添加了Supplier,则调用Supplier来得到对象
    		// 没什么用不用管
    		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    		if (instanceSupplier != null) {
    			return obtainFromSupplier(instanceSupplier, beanName);
    		}
    		// @Bean对应的BeanDefinition
    		//调用@bean注解下面的方法创建bean
    		if (mbd.getFactoryMethodName() != null) {
    			return instantiateUsingFactoryMethod(beanName, mbd, args);
    		}
    		// Shortcut when re-creating the same bean...
    		// 一个原型BeanDefinition,会多次来创建Bean,那么就可以把该BeanDefinition所要使用的构造方法缓存起来,避免每次都进行构造方法推断
    		boolean resolved = false;
    		boolean autowireNecessary = false;
    		//这个if用来判断 构造方法的缓存
    		// 如果传进来的构造方法参数没有值 才会找缓存
    		if (args == null) {
    			synchronized (mbd.constructorArgumentLock) {
    				//resolvedConstructorOrFactoryMethod 缓存构造方法
    				if (mbd.resolvedConstructorOrFactoryMethod != null) {
    					resolved = true;
    					// 判断有没有缓存构造方法的参数 有则返回true 没有返回false
    					autowireNecessary = mbd.constructorArgumentsResolved;
    				}
    			}
    		}
    		// 判断是否缓存了构造方法  缓存有则进入这个if
    		if (resolved) {
    			// 如果确定了当前BeanDefinition的构造方法,那么看是否需要进行对构造方法进行参数的依赖注入(构造方法注入)
    			// 判断 是否缓存有构造方法的入参  如果有执行if方法  没有执行else方法
    			if (autowireNecessary) {
    				// 这个方法会获取 缓存好的构造方法的入参 然后调用缓存的构造方法
    				return autowireConstructor(beanName, mbd, null, null);
    			}
    			else {
    				// 如果不需要注入,则表示用的是默认无参构造方法,直接进行实例化
    				return instantiateBean(beanName, mbd);
    			}
    		}
    		// 没有缓存 就执行下面的方法
    		// Candidate constructors for autowiring?
    		// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪个构造方法
    		// 这个方法用来找合适的构造方法
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    
    		// 如果ctors有值则需要进行构造方法注入,或者autowiredMode是AUTOWIRE_CONSTRUCTOR
    		// 或者BeanDefinition中添加了构造方法的参数和值,或者调用getBean()方法时传入了args
    		// 构造方法注入:首先包括
    		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);
    		}
    
    		// No special handling: simply use no-arg constructor.
    		// 如果没有@Autowired注解的构造方法,当前BeanDefinition的autowiremode也不是AUTOWIRE_CONSTRUCTOR,也没有指明所要用的构造方法参数值
    		// 则直接使用无参构造方法
    		return instantiateBean(beanName, mbd);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    这部分流程大概是

    1. 首先通过Class beanClass = resolveBeanClass(mbd, beanName);根据RootBeanDefinition 和beanName 加载对应的类。
    2. if (mbd.getFactoryMethodName() != null) 这部分是判断@Bean注解暂时不管。
    3. 接下来就是判断当入参为null时找构造方法的缓存。如果有缓存,接着判断有没有缓存构造方法的参数,如果有根据缓存的方法和参数进行调用。如果没有,执行instantiateBean(beanName, mbd)这个方法是调用无参构造方法。
    4. 当没有构造方法的缓存或者入参不为null时 根据Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);这个方法找到合适的构造方法。
    5. 如果找到了合适的构造方法即ctors不为空,那么autowireConstructor(beanName, mbd, ctors, args) 调用对应的构造方法。
    6. 如果没有找到即ctors 为null,直接调用无参构造。

    如果找构造方法
    Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 这个方法就是找适合的构造方法的,那么来看看它是如何找的
    在这里插入图片描述
    它底层会调用到AutowiredAnnotationBeanPostProcessordetermineCandidateConstructors方法。
    这部分代码很长,截取一些重要的代码展示

    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
    		if (candidateConstructors == null) {
    			// Fully synchronized resolution now...
    			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);
    					//记录构造方法@autowire注解的require为true的构造方法 一个类中只能有一个require为true的构造方法
    					Constructor<?> requiredConstructor = null;
    					//记录无参构造
    					Constructor<?> defaultConstructor = null;
    					// 遍历每个构造方法
    					for (Constructor<?> candidate : rawCandidates) {
    						// 当前遍历的构造方法是否写了@Autowired
    						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
    						if (ann == null) {
    							// 如果beanClass是代理类,则得到被代理的类的类型
    							Class<?> userClass = ClassUtils.getUserClass(beanClass);
    							if (userClass != beanClass) {
    								try {
    									//获取被代理类的所有构造方法
    									Constructor<?> superCtor =
    											userClass.getDeclaredConstructor(candidate.getParameterTypes());
    									//从这些构造方法中找有@Autowired注解的构造方法
    									ann = findAutowiredAnnotation(superCtor);
    								}
    								catch (NoSuchMethodException ex) {
    									// Simply proceed, no equivalent superclass constructor found...
    								}
    							}
    						}
    
    						// 如果找到了有@Autowired的构造方法 进入这个if
    						if (ann != null) {
    							// 整个类中如果有一个required为true的构造方法,那就不能在有其他的加了@Autowired的构造方法
    							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);
    								}
    								// 记录唯一一个required为true的构造方法
    								requiredConstructor = candidate;
    							}
    							//上面这两个if 就是判断了有没有多个@Autowired的构造方法  如果有的话 判断@Autowired的required是不是true
    							// 如果是true 那么就会报错  因为一个类只允许有一个@Autowired的required为true的构造方法
    							// 如果存在了 @Autowired的required为true的构造方法 那么其他构造方法不能再加@Autowired
    
    							// 记录所有加了@Autowired的构造方法
    							candidates.add(candidate);
    						}
    						// 如果构造方法的参数 == 0 进入这个if
    						else if (candidate.getParameterCount() == 0) {
    							// 记录唯一一个无参的构造方法
    							defaultConstructor = candidate;
    						}
    
    						// 有可能存在有参、并且没有添加@Autowired的构造方法
    					}
    
    					//遍历完成
    					if (!candidates.isEmpty()) {
    						// Add default constructor to list of optional constructors, as fallback.
    						// 如果不存在一个required为true的构造方法,则所有required为false的构造方法和无参构造方法都是合格的
    						if (requiredConstructor == null) {
    							//如果没有required为true的构造方法 并且无参构造方法也没有 就会报错
    							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));
    							}
    						}
    						// 如果只存在一个required为true的构造方法,那就只有这一个是合格的
    						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
    					}
    					// 没有添加了@Autowired注解的构造方法,并且类中只有一个构造方法,并且是有参的
    					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
    						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
    					}
    					else {
    						// 如果有多个有参、并且没有添加@Autowired的构造方法,是会返回空的
    						candidateConstructors = new Constructor<?>[0];
    					}
    					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
    				}
    			}
    		}
    		return (candidateConstructors.length > 0 ? candidateConstructors : null);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118

    这部分代码的流程大概是:

    1. 首先通过双重检查锁判断有没有缓存有构造方法,如果有直接放回,如果没有通过反射获取到所有构造方法。
    2. 遍历每个构造方法,判断每个方法有没有@Autowired注解,如果没有判断是不是代理类,如果是则找父类有没有@Autowired注解。
    3. 如果该构造方法有@Autowired注解,并且required属性为为true,那么把该构造方法记录下来,如果早已存在了其他标注有@Autowired注解的构造方法,或者存在其他@Autowired并且required属性为为true的构造方法都会报错(也就是说一个类只能存在一个@Autowired并且required属性为为true的构造方法。或者存在多个@Autowired并且required属性为为false的构造方法)。然后candidates这个集合添加标注有@Autowired注解的构造方法。
    4. 如果该构造方法没有@Autowired注解,判断该构造方法的参数是不是为0,如果是记录该无参构造
    5. 遍历完成后,判断candidates集合如果不为空,再接着判断如果没有一个@Autowired并且required属性为为true的构造方法,或者无参构造,就会报错。如果不报错,就把candidates转成一个Constructor[]类型的数组
    6. 如果candidates为空,并且只有一个有参构造方法,记录到Constructor[]类型的数组中,其他情况下返回null

    AutowiredAnnotationBeanPostProcessor中推断构造方法不同情况思维脑图:https://www.processon.com/view/link/6146def57d9c08198c58bb26

    找到构造方法后如何推断
    Constructor[]数组不为空的时候,或者autowiredMode是AUTOWIRE_CONSTRUCTOR或者BeanDefinition中添加了构造方法的参数和值,或者调用getBean()方法时传入了args。满足上述其中一个条件的时候就会调用autowireConstructor(beanName, mbd, ctors, args);这个方法用来推断构造方法。这个过程比较复杂

    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;
    
    		// 如果getBean()传入了args,那构造方法要用的入参就直接确定好了
    		if (explicitArgs != null) {
    			argsToUse = explicitArgs;
    		}
    		//从缓存中获取
    		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);
    			}
    		}
    
    		// 如果没有确定要使用的构造方法,或者确定了构造方法但是所要传入的参数值没有确定
    		if (constructorToUse == null || argsToUse == null) {
    
    			// Take specified constructors, if any.
    			Constructor<?>[] candidates = chosenCtors;
    			if (candidates == null) {
    				Class<?> beanClass = mbd.getBeanClass();
    				try {
    					// 如果没有指定构造方法,那就获取beanClass中的所有构造方法作为候选者
    					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;
    				}
    			}
    
    			// Need to resolve the constructor.
    			boolean autowiring = (chosenCtors != null ||
    					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
    			ConstructorArgumentValues resolvedValues = null;
    
    			// 确定要选择的构造方法的参数个数的最小值,后续判断候选构造方法的参数个数如果小于minNrOfArgs,则直接pass掉
    			int minNrOfArgs;
    			if (explicitArgs != null) {
    				// 如果直接传了构造方法参数值,那么所用的构造方法的参数个数肯定不能少于 传入的参数值的个数
    				minNrOfArgs = explicitArgs.length;
    			}
    			else {
    				// 如果通过BeanDefinition传了构造方法参数值,因为有可能是通过下标指定了
    				// 比如0位置的值,2位置的值,虽然只指定了2个值,但是构造方法的参数个数至少得是3个
    				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
    				resolvedValues = new ConstructorArgumentValues();
    				//通过resolveConstructorArguments 这个方法返回 至少要有多少个参数
    				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
    			}
    
    			// 对候选构造方法进行排序,public的方法排在最前面,都是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) {
    					// Already found greedy constructor that can be satisfied ->
    					// do not look any further, there are only less greedy constructors left.
    					break;
    				}
    				// 如果参数个数小于所要求的参数个数,则遍历下一个,这里考虑的是同时存在public和非public的构造方法
    				if (parameterCount < minNrOfArgs) {
    					continue;
    				}
    
    				ArgumentsHolder argsHolder;
    				//获取构造方法参数的类型
    				Class<?>[] paramTypes = candidate.getParameterTypes();
    				// 如果通过BeanDefinition指定了构造方法参数值
    				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);
    							}
    						}
    
    						// 根据参数类型、参数名找到相应的构造方法和参数的bean  封装成一个对象返回
    						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 {
    					// Explicit arguments given -> arguments length must match exactly.
    					// 没有通过BeanDefinition指定构造方法参数值,但是在调getBean方法是传入了参数值,那就表示只能用对应参数个数的构造方法
    					if (parameterCount != explicitArgs.length) {
    						continue;
    					}
    					// 不用再去BeanFactory中查找bean对象了,已经有了,同时当前正在遍历的构造方法就是可用的构造方法
    					argsHolder = new ArgumentsHolder(explicitArgs);
    				}
    
    				// 当前遍历的构造方法所需要的入参对象都找到了,根据参数类型和找到的参数对象计算出来一个匹配值,值越小越匹配
    				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
    						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
    				// Choose this constructor if it represents the closest match.
    				// 值越小越匹配
    				if (typeDiffWeight < minTypeDiffWeight) {
    					constructorToUse = candidate;
    					argsHolderToUse = argsHolder;
    					argsToUse = argsHolder.arguments;
    					minTypeDiffWeight = typeDiffWeight;
    					ambiguousConstructors = null;
    				}
    				// 值相等的情况下,记录一下匹配值相同的构造方法
    				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
    					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)");
    			}
    			// 如果有可用的构造方法,但是有多个
    			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);
    			}
    
    			// 如果没有通过getBean方法传入参数,并且找到了构造方法以及要用的入参对象则缓存
    			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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    1. 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化
    2. 如果没有确定的构造方法或构造方法参数值,那么
      如果没有确定的构造方法,那么则找出类中所有的构造方法
      如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化
      如果有多个可用的构造方法或者当前Bean需要自动通过构造方法注入
      根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数
      对所有的构造方法进行排序,参数个数多的在前面
      遍历每个构造方法
      如果不是调用getBean方法时所指定的构造方法参数值,那么则根据构造方法参数类型找值
      如果时调用getBean方法时所指定的构造方法参数值,就直接利用这些值
      如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的

    推断构造方法源码到此分析结束,推断构造方法比较复杂,只分析了重点的部分,还有很多细枝末节没有分析到。例如如何算分,如何根据入参获取到bean的类型,@Bean的方式等等没有分析。后续这部分内容不在分析,对于源码关注重点就好。

  • 相关阅读:
    数据库------E-R图和关系模型
    使用windeployqt.exe打包QT工程,windows系统可执行程序
    【洛谷】P3378 【模板】堆
    deque(双端数组)——STL
    word批量修改表格样式
    Netty(1)三大组件
    【RPC框架、RPC框架必会的基本知识、手写一个RPC框架案例、优秀的RPC框架Dubbo、Dubbo和SpringCloud框架比较】
    视频编码基础知识
    计算机毕业设计(附源码)python支持协作知识建构的Python程序设计课程学习活动平台
    NISP和CISP都有什么同?
  • 原文地址:https://blog.csdn.net/admin522043032/article/details/126098389