spring5.0 源码解析 createBeanInstance 09

createBeanInstance

实例化bean

  1. 检查bean 是否可以实例化
  2. spring 5.0 后 AbstractBeanDefinition 了增加 Supplier<?> instanceSupplier 可以利用回调的方式取创建对象
  3. 检查是否有工厂方法,如果有使用工厂方法实例化
  4. 检查缓存(在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析)
  5. 解析构造函数并进行实例化
    因为一个类可能有多个构造函数,所以需要根据配置文件中配置的参数或者传入的参数确定最终调用的构造函数。因为判断过程会比较消耗性能,所以Spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。在下次创建相同bean的时候,会直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析。
  6. 检查是否可以使用构造函数初始化
  7. 使用默认的构造函数初始化
    createBeanInstance 其中的难点就是推断构造方法的过程

autowireConstructor(beanName, mbd, null, null)

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;

		// 1. 解析构造函数参数
		// explicitArgs  参数是通过 getBean 方法传入
		// 如果 getBean在调用时传入了参数,那么直接使用即可。
		// getBean 调用的传参,不用从缓存中获取构造函数,需要进行筛选匹配(个人理解,getBean 方法的入参可能并不相同,缓存的构造函数可能并不适用)
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			// 否则 尝试从 BeanDefinition 中加载缓存的bean构造时需要的参数
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				// 从缓存中获取要使用的构造函数。
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				// 如果构造函数不为空 && 构造函数参数已经解析
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					// 从缓存中获取。这里如果不能获取到完全解析好的参数,则获取尚未解析的参数,进行解析后再赋值给 argsToUse
					// resolvedConstructorArguments 是完全解析好的构造函数参数
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						// 配置构造函数参数
						// preparedConstructorArguments 是尚未完全解析的构造函数参数
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			//  如果缓存中存在 尚未完全解析的参数列表,则进行进一步的解析
			if (argsToResolve != null) {
				// 解析参数类型,如给定的参数列表为(int,int),这时就会将配置中的("1", "1") 转化为 (1,1)
				// 缓存中的值可能是最终值,也可能是原始值,因为不一定需要类型转换
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}

		// 如果构造函数 和 构造函数入参都不为空,则可以直接生成bean。否则的话,需要通过一定的规则进行筛选
		if (constructorToUse == null || argsToUse == null) {
			// Take specified constructors, if any.
			// 获取候选的构造参数列表
			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					// 反射获取bean的构造函数集合
					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);
				}
			}
			// 如果构造函数只有一个 && getBean 没有传参 && 构造参数无参
			// 满足上述三个条件,则无需继续筛选构造函数,直接使用唯一一个构造函数创建 BeanWrapper 并返回即可。
			if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Constructor<?> uniqueCandidate = candidates[0];
				// 确定该构造函数无参
				if (uniqueCandidate.getParameterCount() == 0) {
					// 将解析结束的信息缓存到 mdb中
					// 缓存解析出来的唯一构造函数
					synchronized (mbd.constructorArgumentLock) {
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						// 标记构造函数已经完全解析
						mbd.constructorArgumentsResolved = true;
						// 缓存解析好的构造函数参数。这里是空数组 (Object[] EMPTY_ARGS = new Object[0];)
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			// Need to resolve the constructor.
			//  待选构造函数列表不为null || 需要构造注入,则需要解析。
			//  mbd.getResolvedAutowireMode() 是针对 xml 注入的
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			// 解析出来的构造函数的个数
			int minNrOfArgs;
			// 如果explicitArgs  不为空,直接使用它作为参数,毕竟是传入的参数,没必要再从进一步解析。
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				// 获取配置文件中的配置的构造函数参数
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				// 用于承载解析后的构造函数参数的值
				resolvedValues = new ConstructorArgumentValues();
				// 确定解析到的构造函数参数个数并进行类型转换匹配。
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}

			// 4. 寻找最匹配的构造函数
			// 对构造函数列表进行排序: 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();
				// 如果已经找到选用的构造函数 (argstoUse != null) 或者  需要的构造函数的参数个数 小于 当前构造函数参数个数 则终止
				// constructorToUse != null 说明找到了构造函数
				// argsToUse != null 说明参数已经赋值
				// argsToUse.length > parameterCount
				// 即已经找到适配的构造函数(可能不是最终的,但参数数量一定相同), 预选构造函数的参数数量 大于 当前构造函数的数量,可以直接break,因为按照参数数量降序排序,这里如果小于就没有必要继续比较下去
				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;
				}
				if (parameterCount < minNrOfArgs) {
					// 参数数量不相等,跳过
					continue;
				}
				// 到这里说明尚未找到构造函数,且目前的构造函数和需要的构造函数参数个数相同,下面要对类型进行比较
				ArgumentsHolder argsHolder;
				// 如果构造函数存在参数,resolvedValues 是上面解析后的构造函数,有参则根据 值 构造对应参数类型的参数
				Class<?>[] paramTypes = candidate.getParameterTypes();
				if (resolvedValues != null) {
					try {
						// 获取参数名称
						// 从 @ConstructorProperties 注解上获取参数名称
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
						// 为null则说明没有使用注解
						if (paramNames == null) {
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								// 获取指定的构造函数的参数名称
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						// 根据类型和数据类型创建 参数持有者
						// 这里会调用  DefaultListableBeanFactory#resolveDependency 方法来解析依赖关系
						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.
					// 如果构造函数为默认构造函数,没有参数,如果参数不完全一致则跳过
					// Explicit arguments given -> arguments length must match exactly.
					if (parameterCount != explicitArgs.length) {
						continue;
					}
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				// 探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				// 如果他是当前最接近匹配则选择作为构造函数,因为可能有多个构造函数都同时满足,比如构造函数参数类型全是 Object,选择最合适的(typeDiffWeight 最小的)作为最终构造函数
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					// 如果 已经找到候选构造函数,且当前这个构造函数也有相同的类似度则保存到 ambiguousConstructors 中。后面用于抛出异常
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}
			// 如果 constructorToUse  构造函数为  null,则查找构造函数失败,抛出异常
			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");
		// 将构建的实例加入BeanWrapper 中
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}

instantiateBean的策略

  1. instantiateBean(String beanName, RootBeanDefinition mbd)
    使用其默认构造函数实例化给定bean。
    这里使用的是 CglibSubclassingInstantiationStrategy 策略实例化bean
try {
			Object beanInstance;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged(
						(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
						getAccessControlContext());
			}
			else {
				// 获取实例化策略 并且实例化bean  
				// CglibSubclassingInstantiationStrategy.instantiate
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}

spring 提供了两种生成Bean对象方法,一种是通过 BeanUtils,它使用JVM反射功能,一种是通过CGlib来生成

  • CglibSubclassingInstantiationStrategy 通过CGlib来生成
  • SimpleInstantiationStrategy 通过反射来生成
	public AbstractAutowireCapableBeanFactory() {
		super();
		ignoreDependencyInterface(BeanNameAware.class);
		ignoreDependencyInterface(BeanFactoryAware.class);
		ignoreDependencyInterface(BeanClassLoaderAware.class);
		// 这个方法我也没看懂 应该是返回是否在本机映像上构件程序
		if (NativeDetector.inNativeImage()) {
			this.instantiationStrategy = new SimpleInstantiationStrategy();
		}
		else {
			this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1999

每人一点点,明天会更好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值