Previous posts:

1. Deep understanding of Spring IOC(I), unified resource loading

2. Deep understanding of Spring IOC(ii), from XML to BeanDefinition

3, In-depth understanding of Spring IOC(iii), refresh method before instantiation preparations

4. Deep understanding of Spring IOC

Not talked about in this we speak on a createBean method, is in the last 10 of the block of code is called the method, this method is to be located in AbstractAutowireCapableBeanFactory:

@Override protected Object createBean(Final String beanName, final RootBeanDefinition MBD, final Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } resolveBeanClass(MBD, beanName) {resolveBeanClass(MBD, beanName); Try {/ / 2. The validation and the method of preparing MBD cover attribute MBD prepareMethodOverrides (); }catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } the try {/ / 3. Here is mainly for the agent processing, such as if there is a proxy need to replace the real bean, here is the return result the Object bean = resolveBeforeInstantiation (beanName, MBD); if (bean ! = null) { return bean; } }catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); Object beanInstance = doCreateBean(beanName, MBD, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; }Copy the code

1.1

Block 2 protected Class<? > resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<? >... TypesToMatch) throws CannotLoadBeanClassException {try {/ / have beanClass if MBD, If (mbd.hasbeanclass ()) {return mbd.getBeanclass (); } / / this is still as before, if is privileged exec, else is common way to perform / / is access to the bean's class name if (System. GetSecurityManager ()! = null) { return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<? >>() { @Override public Class<? > run() throws Exception { // 1. The class return doResolveBeanClass(MBD, typesToMatch) that actually resolves the bean; } }, getAccessControlContext()); } else { return doResolveBeanClass(mbd, typesToMatch); } } catch (PrivilegedActionException pae) { ClassNotFoundException ex = (ClassNotFoundException) pae.getException(); throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (LinkageError err) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err); }}Copy the code

Let’s look at block 1 of code 2

Block 3 Private Class<? > doResolveBeanClass(RootBeanDefinition mbd, Class<? >... Throws ClassNotFoundException {// typesToMatch is an empty array, so if (! ObjectUtils.isEmpty(typesToMatch)) { ClassLoader tempClassLoader = getTempClassLoader(); if (tempClassLoader ! = null) { if (tempClassLoader instanceof DecoratingClassLoader) { DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader; for (Class<? > typeToMatch : typesToMatch) { dcl.excludeClass(typeToMatch.getName()); } } String className = mbd.getBeanClassName(); return (className ! = null ? ClassUtils.forName(className, tempClassLoader) : null); } return mbd.resolveBeanClass(getBeanClassLoader());} return mbd.resolveBeanClassLoader (); }Copy the code

1.2

Where prepareMethodOverrides is in AbstractBeanDefinition:

The code block 4 public void prepareMethodOverrides () throws BeanDefinitionValidationException {MethodOverrides MethodOverrides = getMethodOverrides(); // methodOverrides exists and is not null, then the prepared method overrides // both look-up and replace-method if (! methodOverrides.isEmpty()) { for (MethodOverride mo : methodOverrides.getOverrides()) { prepareMethodOverride(mo); }}}Copy the code

The prepareMethodOverride method is called when your XML must use look-upMethod and replace.

Code block 5 protected void prepareMethodOverride (MethodOverride mo) throws BeanDefinitionValidationException {/ / calculate the amount of overloaded methods int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); / / 0 throws an exception if directly (count = = 0) {throw new BeanDefinitionValidationException (" Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]"); // 1 set this property to true, Else if (count == 1) {// Mark override as not overloaded, to avoid the overhead of arg type checking. mo.setOverloaded(false); }}Copy the code

1.3

For example, when you use the @Reference annotation in Dubbo to inject a service object, this is where you go. Let’s look at the code:

The code block 6 protected Object resolveBeforeInstantiation (String beanName, RootBeanDefinition MBD) {Object bean = null; / / if you need to advance execution InstantiationAwareBeanPostProcessor postProcessBeforeInstantiation method of the if (! Boolean. FALSE. Equals (MBD) beforeInstantiationResolved)) {/ / MBD has the correct class attribute && MBD synthetic && InstantiationAwareBeanPostProcessor (this is a special BeanPostProcessor) if (MBD) hasBeanClass () &&! mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { // 1. Perform bean = applyBeanPostProcessorsBeforeInstantiation postProcessBeforeInstantiation method (MBD getBeanClass (), beanName); If result is returned, all of the BeanPostProcessor's post-processing methods are executed. If (bean! = null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } mbd.beforeInstantiationResolved = (bean ! = null); } return bean; }Copy the code

We can see that this is primarily to perform InstantiationAwareBeanPostProcessor, why in the code block 1.3 call here? To give the proxy class a chance to replace the original object, the next step is to call doCreateBean at block 1.4 to create the actual bean instance. Then let’s look at the code block 6 in 1 place, here is actually InstantiationAwareBeanPostProcessor corresponds to the execution

The code block 7 protected Object applyBeanPostProcessorsBeforeInstantiation (Class <? > beanClass, String beanName) throws BeansException {// Throw BeanPostProcessor for (BeanPostProcessor bp: GetBeanPostProcessors ()) {/ / if this was a BeanPostProcessor InstantiationAwareBeanPostProcessor if (bp) instanceof InstantiationAwareBeanPostProcessor) {/ / forced transformation InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result ! = null) { return result; } } } return null; }Copy the code

1.4

Finally to this doCreateBean method, here is the real create bean method, also include one of the most logical method, we don’t empty it, is dry, dry before, however, because of the reason of this method is too complicated, I’ll give you an outline, from on macroscopic to tell you the method does something, give you see the source code, That way you won’t be overwhelmed

This doCreateBean method does these things: 1. Create an object from either a factory method or a constructor (depending on your configuration, this contains the most logic and involves constructor selection) 2. Next comes the loop-dependent processing, mainly through the way of exposure in advance. 3. The filling of attributes and initialization operations, initialization includes bean pre and post processing.

Next, let’s look at the code:

Protected Object doCreateBean(Final String beanName, Final RootBeanDefinition MBD, BeanWrapper instanceWrapper = null; // BeanWrapper instanceWrapper = null; If (mbd.issingleton ()) {// Remove the factoryBean from the cache that you are creating. At the same time removing) instanceWrapper = this. FactoryBeanInstanceCache. Remove (beanName); } if (instanceWrapper == null) { // 1. InstanceWrapper = createBeanInstance(beanName, MBD, args); } final Object bean = (instanceWrapper ! = null ? instanceWrapper.getWrappedInstance() : null); Class<? > beanType = (instanceWrapper ! = null ? instanceWrapper.getWrappedClass() : null); / / use MergedBeanDefinitionPostProcessor modify RootBeanDefinition / / mainly deal with @autowired, @ inject, @ the value standard of the methods and properties / / back from here, Spring knows which method or property has the annotation synchronized (mbd.postProcessingLock) {if (! mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } // earlySingletonExposure is used to determine whether to expose the semi-finished product in advance. The current bean is a work-in-progress because it has not yet been populated with properties, // MBD is a singleton && allows circular references (default true) && Whether the current bean is being created Boolean earlySingletonExposure = (mbD.isSingleton () && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // Expose the beanName corresponding ObjectFactory in advance, AddSingletonFactory (beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { // 2. When using SmartInstantiationAwareBeanPostProcessor return early bean semi-finished products of reference / / if there is no SmartInstantiationAwareBeanPostProcessor, Return getEarlyBeanReference(beanName, MBD, bean); }}); } // Initialize Object exposedObject = bean; Try {// 3. Fill the bean with properties populateBean(beanName, MBD, instanceWrapper); if (exposedObject ! = null) {// 4. Initialize exposedObject = initializeBean(beanName, exposedObject, MBD); } }catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; }else { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); If (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference ! = null) {if (exposedObject == bean) {// due to the operation after init, earlySingletonReference and exposedObject may not bean instance, // We need them to point to an instance, exposedObject = earlySingletonReference; }else if (! Enclosing allowRawInjectionDespiteWrapping && hasDependentBean (beanName)) {/ / get the current bean rely on all String bean array [] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); For (String dependentBean: dependentBeans) {// Remove the bean because the bean depends on the enhanced bean if (! RemoveSingletonIfCreatedForTypeCheckOnly (dependentBean)) {/ / remove added to actualDependentBeans failure actualDependentBeans.add(dependentBean); } } if (! actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); Try {}}}} / / registered for the destruction of the bean, registerDisposableBeanIfNecessary (beanName, bean, MBD); }catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }Copy the code

This doCreateBean method is the core of the whole Spring bean process, of course, the difficulty is also relatively high, this part of the code is required to read repeatedly, the best you can read my article at the same time to follow the source code. The most difficult method of all is the code from # 1, which creates an “incomplete” bean. Why is it incomplete? This is because the bean created at this point has not yet been populated with attributes, that is, the attributes tagged by @AutoWired and @Resource have not yet been injected. Let’s take a look at this method:

Protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition MBD, Object[] args) {resolveBeanClass <? > beanClass = resolveBeanClass(mbd, beanName); &&beanClass is not null &&beanClass is not public &&beanClass does not allow access to non-public constructors Because there's no constructor to call 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()); } // If factory-method is present, create BeanWrapper with factory-method if (mbd.getFactoryMethodName()! = null) {/ / 1. According to the factory method to create instances return with the bean instance BeanWrapper instantiateUsingFactoryMethod (beanName, MBD, args); } // Resolved constructor or factory method resolved. AutowireNecessary means resolved constructor parameter Boolean resolved = false; boolean autowireNecessary = false; If (args = = null) {synchronized (MBD) constructorArgumentLock) {/ / resolvedConstructorOrFactoryMethod isn't empty, that has been parsed, Resolved the to true if (MBD resolvedConstructorOrFactoryMethod! = null) { resolved = true; / / constructorArgumentsResolved if it is true, That autowireNecessary affirmation is true / / constructorArgumentsResolved source notes mean whether constructor parameters has been parsed autowireNecessary = mbd.constructorArgumentsResolved; Error: resolved (resolved) {autowireNecessary {// 2. The only way to get this far is if your bean is a prototype that can be parsed multiple times, // This is true when prototype is resolved and is a constructor injection and autowireNecessary Return autowireConstructor(beanName, MBD, null, null); }else {// 3. Inject return instantiateBean(beanName, MBD) with no-argument constructor; }} // get the candidate Constructor, Constructor<? >[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); / / the candidate construction method is not empty | | constructor injection way | | a constructor parameter values in the MDB | | parameter is not null / / explain in detail the four conditions: (1) The candidate constructor is not empty if the annotation case has @autowired or @inject marked constructor or if your class has only one argument constructor // Or you have achieved SmartInstantiationAwareBeanPostProcessor determineCandidateConstructors method / / (2) is the constructor injection, (3) or the required constructor is a parameterized constructor (because sometimes our class defines only one parameterized constructor), and the argument passed in or is not null if (ctors! = null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() | |! Objectutils.isempty (args)) {return autowireConstructor(beanName, MBD, ctors, args); } // Inject return instantiateBean(beanName, MBD) with no-argument constructor; }Copy the code

9.1

The code block 10 protected BeanWrapper instantiateUsingFactoryMethod (String beanName, RootBeanDefinition MBD, Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }Copy the code

We can see that these are only direct call of ConstructorResolver instantiateUsingFactoryMethod, this method is a very long is also a more complex method, Let’s go straight to ConstructorResolver and look at this method:

                                    代码块11
                                     
public BeanWrapper instantiateUsingFactoryMethod(
			final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {

	// new 一个bw, bw也是方法的结果
	BeanWrapperImpl bw = new BeanWrapperImpl();
	// 对bw进行起码的初始化,这句可以先跳过,你只要知道是个起码的初始化即可
	this.beanFactory.initBeanWrapper(bw);

	Object factoryBean;
	Class<?> factoryClass;
	boolean isStatic;
	
	// 拿到factoryBean的Name,xml中对应factory-bean属性
	String factoryBeanName = mbd.getFactoryBeanName();
	if (factoryBeanName != null) {
		// 如果factoryBeanName 和 目标bean的名称是一样的,则直接抛异常
		// 这个是指xml中bean标签的factory-bean和id属性值不能一样
		if (factoryBeanName.equals(beanName)) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
					"factory-bean reference points back to the same bean definition");
		}
		// 拿到factoryBeanName对应的bean,即beanName对应bean的factory类
		factoryBean = this.beanFactory.getBean(factoryBeanName);
		// 是null抛异常,因为根本没有这个factoryBean或者其创建出来的对象
		if (factoryBean == null) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"factory-bean '" + factoryBeanName + "' (or a BeanPostProcessor involved) returned null");
		}
		factoryClass = factoryBean.getClass();
		isStatic = false;
	}else {
		// 这个else代码块是静态工厂的处理,静态工厂不会在xml中指定factory-bean
		// 不知道类是哪个的话则抛异常
		if (!mbd.hasBeanClass()) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
					"bean definition declares neither a bean class nor a factory-bean reference");
		}
		factoryBean = null;
		factoryClass = mbd.getBeanClass();
		isStatic = true;
	}

	// 最终要用的方法
	Method factoryMethodToUse = null;
	ArgumentsHolder argsHolderToUse = null;
	// 最终要用的方法的参数
	Object[] argsToUse = null;
	
	// 如果本方法传入的参数不是空则使用的是方法传入的参数
	if (explicitArgs != null) {
		argsToUse = explicitArgs;
	}else {
	// 这个else 代码块主要是在拿已经解析并使用过的方法和方法参数的缓存
		Object[] argsToResolve = null;
		synchronized (mbd.constructorArgumentLock) {
		  // 注意哈,这里便体现出了RootBeanDefiniti缓存的作用了
			// 拿解析过的构造方法或是工厂方法
			factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
			// 已解析过的不为空 && mbd构造方法参数也是有的
			if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
				// 设置argsToUse为mbd解析过的构造方法的参数的缓存
				argsToUse = mbd.resolvedConstructorArguments;
				// 这个是候选的用来解析的
				if (argsToUse == null) {
					argsToResolve = mbd.preparedConstructorArguments;
				}
			}
		}
		// 1. 解析要使用的参数为需要的类型
		if (argsToResolve != null) {
			argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
		}
	}

	if (factoryMethodToUse == null || argsToUse == null) {
		// 这段代码主要是在找哪个方法是静态工厂方法
		factoryClass = ClassUtils.getUserClass(factoryClass);
		// 拿到factoryClass的所有方法
		Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
		List<Method> candidateSet = new ArrayList<Method>();
		for (Method candidate : rawCandidates) {
			// 是静态方法 && 名字和mbd的工厂方法一样
			// 因为即使是静态并且名字是同一个,也存在可能有个多个重载的情况
			// 所以需要存到candidateSet进行进一步的筛选
			if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
				candidateSet.add(candidate);
			}
		}
		// candidateSet转为数组并排序
		Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
		// 给方法排序,public排在非public之前,如果都是public,则参数多的排在前
		AutowireUtils.sortFactoryMethods(candidates);

		// 解析过的参数
		ConstructorArgumentValues resolvedValues = null;
		// 是否为构造器注入,这里一般都是false
		boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		// 最小的权重,指的是参数类型不相同的权重,越小则说明越匹配
		int minTypeDiffWeight = Integer.MAX_VALUE;
		Set<Method> ambiguousFactoryMethods = null;

		// 最少需要的参数个数
		int minNrOfArgs;
		if (explicitArgs != null) {
			minNrOfArgs = explicitArgs.length;
		}else {
			// 拿到beanDefinition中解析到的xml中定义的构造方法参数
			ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
			resolvedValues = new ConstructorArgumentValues();
			// 2.解析参数,并返回参数个数(解析体现在需要把“1”这样的string转化为了int)
			minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
		}

		List<Exception> causes = null;
		
		// 通过各种方式确定最终要使用的工厂方法是哪个,以及其中的参数
		// 遍历candidates
		for (int i = 0; i < candidates.length; i++) {
			// 拿到对应的方法作为候选方法和它的参数
			Method candidate = candidates[i];
			Class<?>[] paramTypes = candidate.getParameterTypes();
			// 如果这个方法的参数大于等于最小需要的参数
			if (paramTypes.length >= minNrOfArgs) {
				ArgumentsHolder argsHolder;

				if (resolvedValues != null) {
					// Resolved constructor arguments: type conversion and/or autowiring necessary.
					try {
						// 参数名数组
						String[] paramNames = null;
						ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
						if (pnd != null) {
							paramNames = pnd.getParameterNames(candidate);
						}
						// 3.解析参数
						argsHolder = createArgumentArray(
								beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
					}catch (UnsatisfiedDependencyException ex) {
						if (this.beanFactory.logger.isTraceEnabled()) {
							this.beanFactory.logger.trace("Ignoring factory method [" + candidate +
									"] of bean '" + beanName + "': " + ex);
						}
						// i为最后一个,&& argsHolderToUse为null (还没找到合适的参数)
						if (i == candidates.length - 1 && argsHolderToUse == null) {
							// 如果有异常,此时也就该抛异常了
							if (causes != null) {
								for (Exception cause : causes) {
									this.beanFactory.onSuppressedException(cause);
								}
							}
							throw ex;
						}else {
							// 如果有异常,就记录下来
							if (causes == null) {
								causes = new LinkedList<Exception>();
							}
							causes.add(ex);
							continue;
						}
					}
				}else {
					if (paramTypes.length != explicitArgs.length) {
						continue;
					}
					argsHolder = new ArgumentsHolder(explicitArgs);
				}

				// 这个就是开始AbstractBeanDefinition中lenientConstructorResolution
				// 那个属性影响到的地方,具体体现在:如果是true,代表只要你的值转换过的类型可以和需要的类型
				// 能匹配上,就是你这个方法了。比如说:getInstance(Integer age),此时xml定义了age为18的参数,而由于xml中定义的参数都会被解析
				// 成String,因此需要转化,如果lenientConstructorResolution为true,则这里就可以匹配上这个方法
				// 因为18可以被转为Integer,如果是false,就不能匹配上这个方法了
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// 根据权重选出最合适的方法和参数,权重小则说明越合适
				// minTypeDiffWeight的值此时是Integer.MAX_VALUE
				if (typeDiffWeight < minTypeDiffWeight) {
					factoryMethodToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousFactoryMethods = null;
				// factoryMethodToUse不为null && 类型差异权重相同 && 不是宽松构造函数解析模式 && 候选方法的参数类型
				// 和factoryMethodToUse的长度相同 && 候选方法数组和factoryMethodToUse的参数类型不一样
				// 注意哈:typeDiffWeight 是不可能比 minTypeDiffWeight 大的,具体原因可以去计算typeDiffWeight
				// 的方法里看
				}else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
						!mbd.isLenientConstructorResolution() &&
						paramTypes.length == factoryMethodToUse.getParameterTypes().length &&
						!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
					// 添加到ambiguousFactoryMethods用作后续的抛异常用
					if (ambiguousFactoryMethods == null) {
						ambiguousFactoryMethods = new LinkedHashSet<Method>();
						ambiguousFactoryMethods.add(factoryMethodToUse);
					}
					ambiguousFactoryMethods.add(candidate);
				}
			}
		}

		// 如果此时factoryMethodToUse还是null,则抛异常
		if (factoryMethodToUse == null) {
			List<String> argTypes = new ArrayList<String>(minNrOfArgs);
			if (explicitArgs != null) {
				for (Object arg : explicitArgs) {
					argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
				}
			}else {
				Set<ValueHolder> valueHolders = new LinkedHashSet<ValueHolder>(resolvedValues.getArgumentCount());
				valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
				valueHolders.addAll(resolvedValues.getGenericArgumentValues());
				for (ValueHolder value : valueHolders) {
					String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
							(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
					argTypes.add(argType);
				}
			}
			String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"No matching factory method found: " +
					(mbd.getFactoryBeanName() != null ?
						"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
					"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
					"Check that a method with the specified name " +
					(minNrOfArgs > 0 ? "and arguments " : "") +
					"exists and that it is " +
					(isStatic ? "static" : "non-static") + ".");
		// 如果factoryMethodToUse返回值类型是void,则抛异常
		}else if (void.class.equals(factoryMethodToUse.getReturnType())) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Invalid factory method '" + mbd.getFactoryMethodName() +
					"': needs to have a non-void return type!");
		// 如果ambiguousFactoryMethods不是null,则抛异常
		}else if (ambiguousFactoryMethods != null) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Ambiguous factory method matches found in bean '" + beanName + "' " +
					"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
					ambiguousFactoryMethods);
		}

		// 将解析出来的参数和方法存到mbd的缓存中
		// 应该还知道mbd是个啥玩意吧?不知道的话赶紧回去看一看
		if (explicitArgs == null && argsHolderToUse != null) {
			argsHolderToUse.storeCache(mbd, factoryMethodToUse);
		}
	}

	// 到这块已经找到了要用的方法,以及要用的参数,可以去根据方法去创建对象了
	try {
		Object beanInstance;
		// 应用特权创建或者是普通创建
		if (System.getSecurityManager() != null) {
			final Object fb = factoryBean;
			final Method factoryMethod = factoryMethodToUse;
			final Object[] args = argsToUse;
			beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					// 这里本质上还是在用反射调用
					return beanFactory.getInstantiationStrategy().instantiate(
							mbd, beanName, beanFactory, fb, factoryMethod, args);
				}
			}, beanFactory.getAccessControlContext());
		}else {
			beanInstance = beanFactory.getInstantiationStrategy().instantiate(
					mbd, beanName, beanFactory, factoryBean, factoryMethodToUse, argsToUse);
		}

		if (beanInstance == null) {
			return null;
		}
		bw.setWrappedInstance(beanInstance);
		return bw;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
	}
}
Copy the code

Is really a very long way, so I was as far as possible is within the code, don’t let you in the way so long is also in the case of the incised on the screen, even if like this, it is still not so simple, a lot of people also stop by this code, see my article the reader, if you see here, I feel you still need to be, Because you’ve already been to a place like this, and once you’ve done that, the rest is easy.

11.1

This is mainly the parsing of parameters, that is, converting a given parameter to the correct type

Private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition MBD, BeanWrapper BW, Member methodOrCtor, Object[] argsToResolve) {Constructor = methodOrCtor; >[] paramTypes = (methodOrCtor instanceof Method ? ((Method) methodOrCtor).getParameterTypes() : ((Constructor<? >) methodOrCtor).getParameterTypes()); / / type converter TypeConverter converter = (this) the beanFactory) getCustomTypeConverter ()! = null ? this.beanFactory.getCustomTypeConverter() : bw); / / value converter BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver (enclosing the beanFactory, beanName, MBD, converter); // Result Object[] resolvedArgs = new Object[argstoresolv.length]; for (int argIndex = 0; argIndex < argsToResolve.length; ArgIndex ++) {Object argValue = argsToResolve[argIndex]; MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, argIndex); GenericTypeResolver.resolveParameterType(methodParam, methodOrCtor.getDeclaringClass()); if (argValue instanceof AutowiredArgumentMarker) { argValue = resolveAutowiredArgument(methodParam, beanName, null, converter); }else if (argValue instanceof BeanMetadataElement) { argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue); }else if (argValue instanceof String) { argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd); } // We can see from this that what we are doing is changing "1" to "1", that is, converting the argument to the desired type Class<? > paramType = paramTypes[argIndex]; try { resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam); } catch (TypeMismatchException ex) { String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method"); throw new UnsatisfiedDependencyException( mbd.getResourceDescription(), beanName, argIndex, paramType, "Could not convert " + methodType + " argument value of type [" + ObjectUtils.nullSafeClassName(argValue) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage()); } } return resolvedArgs; }Copy the code

11.2

Here, too, it parses parameters, but here it parses a given parameter in the XML and returns the minimum number of parameters needed, and here it is possible to find the dependent bean

Code block 13 private int resolveConstructorArguments (String beanName, RootBeanDefinition MBD, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {/ / type converter and value the parser TypeConverter converter = (this.beanFactory.getCustomTypeConverter() ! = null ? this.beanFactory.getCustomTypeConverter() : bw); BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); int minNrOfArgs = cargs.getArgumentCount(); // Here is the parameter with index in the tag, If there is no match the index / / that will not go for the cycle (Map. Entry < Integer, ConstructorArgumentValues ValueHolder > Entry: cargs.getIndexedArgumentValues().entrySet()) { int index = entry.getKey(); / / the index cannot be less than zero if (index < 0) {throw new BeanCreationException (MBD) getResourceDescription (), beanName, "Invalid constructor argument index: " + index); If (index > minNrOfArgs) {minNrOfArgs = index +1; if (index > minNrOfArgs) {minNrOfArgs = index +1; } / / get the corresponding value ConstructorArgumentValues. ValueHolder ValueHolder = entry. The getValue (); If (valueholder.isconverted ()) {// if (valueholder.isconverted ()) Is directly added to the resolvedValues resolvedValues. AddIndexedArgumentValue (index, valueHolder); }else { Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName()); resolvedValueHolder.setSource(valueHolder); / / will convert the value added to the resolvedValues resolvedValues. AddIndexedArgumentValue (index, resolvedValueHolder); }} / / here is the label with the index of configuration parameters for (ConstructorArgumentValues. ValueHolder ValueHolder: Cargs. GetGenericArgumentValues ()) {/ / conversion, logic, and the same above, In line with resolvedValues // genericArgumentValue if (valueholder.isconverted ()) { resolvedValues.addGenericArgumentValue(valueHolder); }else { Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName()); resolvedValueHolder.setSource(valueHolder); resolvedValues.addGenericArgumentValue(resolvedValueHolder); }} // Return minNrOfArgs; }Copy the code

11.3

Private ArgumentsHolder createArgumentArray(String beanName, RootBeanDefinition MBD, RootBeanDefinition MBD, ConstructorArgumentValues resolvedValues, BeanWrapper bw, Class<? >[] paramTypes, String[] paramNames, Object methodOrCtor, Boolean autowiring) throws UnsatisfiedDependencyException {/ / judgment method type String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method"); / / get type converter TypeConverter converter = (this) the beanFactory) getCustomTypeConverter ()! = null ? this.beanFactory.getCustomTypeConverter() : bw); ArgumentsHolder args = new ArgumentsHolder(paramtypes.length); // Args is the result of this method return ArgumentsHolder args = new ArgumentsHolder(paramtypes.length); // usedValueHolders Used for filtering with the Set < ConstructorArgumentValues. ValueHolder > usedValueHolders = new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length); Set<String> autowiredBeanNames = new LinkedHashSet<String>(4); For (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { Class<? > paramType = paramTypes[paramIndex]; String paramName = (paramNames ! = null ? paramNames[paramIndex] : null); / / according to subscript ConstructorArgumentValues. Get a constructor parameter ValueHolder ValueHolder = resolvedValues. GetArgumentValue (paramIndex, paramType, paramName, usedValueHolders); If (valueHolder == null &&!) if (valueHolder == null &&!) if (valueHolder == null &&!) autowiring) { valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders); } if (valueHolder ! Usedvalueholder = null) {usedValueHolders. Add (valueHolder); Object originalValue = ValueHolder.getValue (); Object convertedValue; / / if the parameter types have been into the direct use of (position) is added to the args if (valueHolder. IsConverted ()) {convertedValue = valueHolder. GetConvertedValue ();  args.preparedArguments[paramIndex] = convertedValue; } else {/ / parameter of type conversion ConstructorArgumentValues. ValueHolder sourceHolder = (ConstructorArgumentValues. ValueHolder) valueHolder.getSource(); Object sourceValue = sourceHolder.getValue(); Try {/ / conversion convertedValue = converter. ConvertIfNecessary (originalValue paramType, MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex)); args.resolveNecessary = true; PreparedArguments [paramIndex] = sourceValue; // Add the converted parameters to the corresponding position in args. PreparedArguments [paramIndex] = sourceValue; } the catch (TypeMismatchException ex) {/ / conversion failed throw new exception UnsatisfiedDependencyException (MBD) getResourceDescription (), beanName, paramIndex, paramType, "Could not convert " + methodType + " argument value of type [" + ObjectUtils.nullSafeClassName(valueHolder.getValue()) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage()); } } args.arguments[paramIndex] = convertedValue; args.rawArguments[paramIndex] = originalValue; }else {// If (! autowiring) { throw new UnsatisfiedDependencyException( mbd.getResourceDescription(), beanName, paramIndex, paramType, "Ambiguous " + methodType + " argument types - " + "did you specify the correct bean references as " + methodType + " arguments?" ); } @autoWired is tagged above the constructor, and @autowired is tagged above the constructor. Need to deal with parameters of bean try {MethodParameter param = MethodParameter. ForMethodOrConstructor (methodOrCtor paramIndex); Object autowiredArgument = resolveAutowiredArgument(param, beanName, autowiredBeanNames, converter); args.rawArguments[paramIndex] = autowiredArgument; args.arguments[paramIndex] = autowiredArgument; args.preparedArguments[paramIndex] = new AutowiredArgumentMarker(); args.resolveNecessary = true; }catch (BeansException ex) { throw new UnsatisfiedDependencyException( mbd.getResourceDescription(), beanName, paramIndex, paramType, ex); } } } for (String autowiredBeanName : AutowiredBeanNames) {/ / registered dependencies enclosing the beanFactory. RegisterDependentBean (autowiredBeanName, beanName); if (this.beanFactory.logger.isDebugEnabled()) { this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName + "' via " + methodType + " to bean named '" + autowiredBeanName + "'"); } } return args; }Copy the code

Code block 11 then said, I don’t know how many people can see it, to be honest, I write this, the author also collapse myself, where I collapse is not how much I don’t think it’s difficult, but I just can’t make this method make you suddenly like a vernacular can read, see the source code, the collapse is clearly a method has been very long, But the somebody else return a cover 1, you saw inside cover of a huge long clinking method after return original method discovery only advanced a line, then a lot of people were persuaded to retreat 😂. In fact, FOR your sake, I did not list some methods in code block 11, but my github source code is annotated, you follow my guide to read the source code, and then follow it again, it will be easier. It’s not easy to keep up, so for those of you who are here, as the authors, give you a thumbs up and let’s cheer together.

In a bit of a touch of my own, block 9.1 is done calling the factory method to create beans, and then 9.2. 9.2 calls the same length of code as 9.1, but the pattern is almost the same, so if you really understand the above, the following one should be easy.

9.2

                                   代码块15
                                     
// 使用构造方法创建bean
public BeanWrapper autowireConstructor(
			final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
		// 创建并初始化BeanWrapper
	BeanWrapperImpl bw = new BeanWrapperImpl();
	this.beanFactory.initBeanWrapper(bw);

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

	// 如果explicitArgs不为null,那最终要用的参数就为explicitArgs
	if (explicitArgs != null) {
		argsToUse = explicitArgs;
	}else {
		Object[] argsToResolve = null;
		synchronized (mbd.constructorArgumentLock) {
			// 先尝试从mbd的缓存拿解析过的构造方法和其对应的参数
			// 注意哈,这块为什么会和之前那个根据工厂方法创建bean用的是一个mbd的变量做缓存的原因是:
			// 一个对象同时只能使用构造方法和工厂方法中的一个去创建(不理解这里的可以多看几遍源码)
			constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
			// 构造方法不为空 && 并且构造函数的参数解析过
			if (constructorToUse != null && mbd.constructorArgumentsResolved) {
				// 缓存中拿已经解析出来的参数
				argsToUse = mbd.resolvedConstructorArguments;
				// 如果已经解析的为空,则去拿候选解析的
				if (argsToUse == null) {
					argsToResolve = mbd.preparedConstructorArguments;
				}
			}
		}
		// 如果argsToResolve不为null,把参数解析为正确的类型,上面已讲过这个方法
		if (argsToResolve != null) {
			argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
		}
	}

	// 如果上面没有从缓存中拿到,则尝试去解析一个最合适的构造方法
	if (constructorToUse == null) {
		boolean autowiring = (chosenCtors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		ConstructorArgumentValues resolvedValues = null;

		// 构造方法参数个数
		int minNrOfArgs;
		// 如果给定的参数数组不是null,则使用给定的参数数组的长度
		if (explicitArgs != null) {
			minNrOfArgs = explicitArgs.length;
		}else {
			// 这里的cargs其实就是我们xml定义的constructor-arg的东西
			ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
			resolvedValues = new ConstructorArgumentValues();
			minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
		}

		// 如果这时候方法参数里的构造方法数组是空的,那么
		// 就去拿beanClass的构造方法
		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);
			}
		}
		
		// 给构造方法排序,public排在非public之前,如果都是public,则参数多的排在前
		AutowireUtils.sortConstructors(candidates);
		// 这块权重的这个套路和之前的是一样的
		int minTypeDiffWeight = Integer.MAX_VALUE;
		Set<Constructor<?>> ambiguousConstructors = null;
		List<Exception> causes = null;

		for (int i = 0; i < candidates.length; i++) {
			// 对应下标的构造方法和其参数
			Constructor<?> candidate = candidates[i];
			Class<?>[] paramTypes = candidate.getParameterTypes();
			// 要用的构造方法不为空 && 其参数的长度大于现在这个下标的构造方法参数长度
			if (constructorToUse != null && argsToUse.length > paramTypes.length) {
				// 跳出循环不再查找,因为对于排序过后的数组来说,现在的constructorToUse已经是最合适的了
				break;
			}
			// 如果这个下标的构造方法的参数小于我们所需要的参数个数,则直接跳过这个构造方法
			if (paramTypes.length < minNrOfArgs) {
				continue;
			}

			ArgumentsHolder argsHolder;
			if (resolvedValues != null) {
				try {
					// 这块是去拿本下标构造方法参数的真正的名字
					String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
					if (paramNames == null) {
						// 如果paramNames还是null则用参数名解析器来解析参数
						ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
						if (pnd != null) {
							paramNames = pnd.getParameterNames(candidate);
						}
					}
					// 去拿最终使用的构造方法的参数,之前讲工厂方法创建对象的时候已说过
					argsHolder = createArgumentArray(
							beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
				}catch (UnsatisfiedDependencyException ex) {
					if (this.beanFactory.logger.isTraceEnabled()) {
						this.beanFactory.logger.trace(
								"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
					}
					// 这个是指到candidates最后一个都还没找到可以用的构造方法,则抛出异常
					if (i == candidates.length - 1 && constructorToUse == null) {
						if (causes != null) {
							for (Exception cause : causes) {
								this.beanFactory.onSuppressedException(cause);
							}
						}
						throw ex;
					// 否则在这里吃掉异常,继续找下一个
					}else {
						// Swallow and try next constructor.
						if (causes == null) {
							causes = new LinkedList<Exception>();
						}
						causes.add(ex);
						continue;
					}
				}
			}else {
				// 参数的长度都不相同,肯定不是一个方法,则直接跳过
				if (paramTypes.length != 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) {
				if (ambiguousConstructors == null) {
					ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
					ambiguousConstructors.add(constructorToUse);
				}
				ambiguousConstructors.add(candidate);
			}
		}
		
		// 没找到构造方法,则抛出异常
		if (constructorToUse == null) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Could not resolve matching constructor " +
					"(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 in bean '" + beanName + "' " +
					"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
					ambiguousConstructors);
		}

		if (explicitArgs == null) {
			argsHolderToUse.storeCache(mbd, constructorToUse);
		}
	}

	try {
		Object beanInstance;
		// 根据策略创建实例
		if (System.getSecurityManager() != null) {
			final Constructor<?> ctorToUse = constructorToUse;
			final Object[] argumentsToUse = argsToUse;
			beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					return beanFactory.getInstantiationStrategy().instantiate(
							mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
				}
			}, beanFactory.getAccessControlContext());
		}
		else {
			beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
					mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
		}
		// 返回结果bw
		bw.setWrappedInstance(beanInstance);
		return bw;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
	}
}
Copy the code

This approach is similar to the overall pattern of code block 11. Of course, this is the last big method in this series, and the rest of the code should be easy for you

9.3

Protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; / / privilege to create or common create, the last is a method to construct the if the call (System. GetSecurityManager ()! = null) { beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { return getInstantiationStrategy().instantiate(mbd, beanName, parent); } }, getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); }}Copy the code

This method is actually a lot of simple, I did not put the inside of the column again, you can go with yourself, believe in your strength at this time, see this method is still small for you.

This completes the createBeanInstance method in block 8 and will continue in the next article.