createBeanInstance 是Spring实例化的核心代码,它根据不同的情况会调用四种实例化方法。
obtainFromSupplier 通过Supplier实例化instantiateUsingFactoryMethod 通过工厂方法autowireConstructor 用合适的构造函数instantiateBean 用无参构造函数第一种很简单,看一下代码就能发现Supplier接口只有一个get方法,就通过这个实例化。 第二第三种比较复杂,也比较相近,本文详细分析。 第四种也很简单,当找不到其它构造函数时,就用无参的,就像兜底的一样。
通过工厂方法进行实例化,简单地想一下,肯定需要下面三个东西:
工厂方法的bean,如果是静态工厂方法的话就不需要这个了。要调用的工厂方法需要传入的参数有了上述概念后,来看代码,代码很长很复杂,但是总体上讲就是先解析上面这三个东西,然后进行实例化。
为了更好理解,省略了部分代码,但还是很长… 代码都有详细的注释,并且很明显地分成了三部分,应该能看懂。
// ConstructorResolver public BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs){ // 建立一个BeanWrapper BeanWrapperImpl bw = new BeanWrapperImpl(); //----------------------------------1. 首先确定factoryBean-------------------------------- // 如果是非静态的,获取factoryBean实例,否则null Object factoryBean; // 工厂类 Class<?> factoryClass; // 非静态false,静态true boolean isStatic; // ... //---------------------2. 确定factoryMethod 和 argsToUse(需要传的参数)--------------------- // 用到的factoryMethod Method factoryMethodToUse = null; ArgumentsHolder argsHolderToUse = null; // 需要传入的参数 Object[] argsToUse = null; //------------------------------2.1 显式传参 或者 从缓存中拿------------------------------- // 如果显式传参就不用去解析参数了,但是要通过2.2解析factoryMethodToUse if (explicitArgs != null) { argsToUse = explicitArgs; } else { // 从缓存中拿 Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { // 获取缓存的方法 factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod; if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) { // 获取缓存的可以直接使用的参数 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 获取缓存的待解析的参数 argsToResolve = mbd.preparedConstructorArguments; } } } // 解析从未解析的参数: 字符串“3” -> 数字3 if (argsToResolve != null) { argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true); } } // 如果通过上述步骤argsToUse 和 factoryMethodToUse 都确定了就直接到第三步,否则到2.2 //-----------------------2.2 argsToUse 或者 factoryMethodToUse还没确定------------------- if (factoryMethodToUse == null || argsToUse == null) { // 获得所有符合条件的method // 条件有两个 1. 如果是静态工厂方法只要static的,否则就只要非static的 2. 是工厂方法 if (candidates == null) { //... } // 只有一个方法且不需要传参,并且配置文件中也没有定义入参。 if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) { // ... // 创建完beanwrapper直接返回 return bw; } // 如果有很多candidates,先按public,非public排序,再按参数量降序 if (candidates.size() > 1) { candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR); } // 从配置文件中解析的参数 ConstructorArgumentValues resolvedValues = null; // autowire == "constructor" boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR); // 类型差分数 int minTypeDiffWeight = Integer.MAX_VALUE; // 类型差分数 并列最低的FactoryMethod们 Set<Method> ambiguousFactoryMethods = null; // 配置文件中直接定义 或者 显式传参的数量 int minNrOfArgs; // 解析配置文件中定义的参数 resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); // 循环每个方法,找最合适的方法 for (Method candidate : candidates) { // ... // 获取解析器 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { // 获取当前方法需要的参数定义 paramNames = pnd.getParameterNames(candidate); } // 根据配置文件中定义好的入参,工厂方法要求的参数,autowiring模式等获得所有参数。 // 如果autowiring不是constructor,那配置文件中的入参就得和方法要求的参数完全一致,否则就 // 会报错 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring, candidates.size() == 1); // 根据实际获得的参数argsHolder和需要的参数,得到类型差异分 int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // 找最小的typeDiffWeight对应的factoryMethodToUse和argsToUse if (typeDiffWeight < minTypeDiffWeight) { factoryMethodToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousFactoryMethods = null; } if (/*有并列的typeDiffWeight*/){ ambiguousFactoryMethods.add(candidate); } } // ... // 存缓存 if (explicitArgs == null && argsHolderToUse != null) { mbd.factoryMethodToIntrospect = factoryMethodToUse; argsHolderToUse.storeCache(mbd, factoryMethodToUse); } //--------------------------------------3. 实例化----------------------------------------- // 根据得到的factoryBean(如果是静态工厂方法就是null),factoryMethodToUse,argsToUse // 进行实例化 bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse)); return bw; }主要就是三部分:
解析工厂类,工厂bean,工厂方法是不是static
找最合适的工厂方法factoryMethodToUse, 和 需要传入的参数argsToUse
2.1 根据static或者不是static找到所有的候选方法
2.2 遍历所有的候选方法,按当前候选方法需要的形参去获得实参(从配置文件中找 或者 可以autowire到的) ,根据形参和实际获得的实参,得到差异分typeDiffWeight,取最小差异分对应的候选方法作为factoryMethodToUse,对应的实参作为argsToUse。
用工厂bean,factoryMethodToUse,argsToUse进行实例化
理清楚了其实也不是很复杂hhhh
这个其实就是低配版的instantiateUsingFactoryMethod。主要少了下面这两部分
不需要工厂,所以不用解析工厂类,工厂bean构造函数没有static的,所以不需要解析isStatic其它部分基本是一样的。就直接看代码吧,这次放完整的代码了。
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); // --------------------------------1. 确定构造函数 和 入参---------------------------------- // 构造函数 Constructor<?> constructorToUse = null; ArgumentsHolder argsHolderToUse = null; // 传入的参数 Object[] argsToUse = null; // -------------------------------1.1 从缓存中拿------------------------------------ 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, true); } } //-----------------------1.2 constructorToUse 或者 argsToUse还没解析出来---------------- if (constructorToUse == null || argsToUse == null) { // Take specified constructors, if any. 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; } } // Need to resolve the 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); } AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<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; } if (parameterCount < minNrOfArgs) { continue; } ArgumentsHolder argsHolder; Class<?>[] paramTypes = candidate.getParameterTypes(); if (resolvedValues != null) { try { 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 LinkedList<>(); } causes.add(ex); continue; } } else { // 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. 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 " + "(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 != null) { argsHolderToUse.storeCache(mbd, constructorToUse); } } // ----------------------------------2 实例化--------------------------------------------- Assert.state(argsToUse != null, "Unresolved constructor arguments"); bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse)); return bw; }从代码可以看出来它只有两部分了,不需要解析工厂相关的东西了,其它差不多。
这个就是调用无参构造函数,就不需要各种解析过程了,直接用就完事了。