spring源码笔记-instantiateUsingFactoryMethod与autowireConstructor两个Bean实例化方法

本人博客原地址:spring源码笔记-instantiateUsingFactoryMethod与autowireConstructor两个Bean实例化方法
创作时间: 2019.06.30 19:34:20

基于springboot2.1.4

1、instantiateUsingFactoryMethod

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod–>org.springframework.beans.factory.support.ConstructorResolver#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)

         public BeanWrapper instantiateUsingFactoryMethod(
 			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);

		Object factoryBean;
		Class<?> factoryClass;
		boolean isStatic;
       // 通过beanDefinition获取到factoryBeanName ,实际就是@Bean注解的方法
        //所在的configuration类
		String factoryBeanName = mbd.getFactoryBeanName();
		if (factoryBeanName != null) {
			if (factoryBeanName.equals(beanName)) {
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"factory-bean reference points back to the same bean definition");
			}
          //  获取configuration类的实例
			factoryBean = this.beanFactory.getBean(factoryBeanName);
			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
				throw new ImplicitlyAppearedSingletonException();
			}
			factoryClass = factoryBean.getClass();
			isStatic = false;
		}
		else {
			// It's a static factory method on the bean class.
			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;

        //如果在调用getBean方法时有传参,那就用传的参作为
        //@Bean注解的方法(工厂方法)的参数,
       // 一般懒加载的bean才会传参,启动过程就实例化的实际上都没有传参
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
             //不为空表示已经使用过工厂方法,现在是再次使用工厂方法,
             //  一般原型模式和Scope模式采用的上,直接使用该工厂方法和缓存的参数
				if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached factory method...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
			}
		}

      //  调用getBean方法没有传参,同时也是第一次使用工厂方法
		if (factoryMethodToUse == null || argsToUse == null) {
			// Need to determine the factory method...
			// Try all methods with this name to see if they match the given arguments.
			factoryClass = ClassUtils.getUserClass(factoryClass);
       // 获取configuration类的所有候选方法
			Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
			List<Method> candidateList = new ArrayList<>();
			for (Method candidate : rawCandidates) {
        // 查找到与工厂方法同名的候选方法,没有@Bean的同名方法不被考虑
				if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
					candidateList.add(candidate);
				}
			}

         //当与工厂方法同名的候选方法只有一个,且调用getBean方法时没有传参,
       //  且没有缓存过参数,直接通过调用实例化方法执行该候选方法
			if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Method uniqueCandidate = candidateList.get(0);
				if (uniqueCandidate.getParameterCount() == 0) {
					mbd.factoryMethodToIntrospect = uniqueCandidate;
					synchronized (mbd.constructorArgumentLock) {
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			Method[] candidates = candidateList.toArray(new Method[0]);
     // 有多个与工厂方法同名的候选方法时,进行排序。public的方法会往前排,然后参数个数多的方法往前排
      //具体排序代码--->org.springframework.beans.factory.support.AutowireUtils#sortConstructors

			ConstructorArgumentValues resolvedValues = null;
			boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Method> ambiguousFactoryMethods = null;

			int minNrOfArgs;
           // 如果调用getBean方法时有传参,那么工厂方法最少参数个数要等于传参个数
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				// We don't have arguments passed in programmatically, so we need to resolve the
				// arguments specified in the constructor arguments held in the bean definition.
				if (mbd.hasConstructorArgumentValues()) {
					ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
					resolvedValues = new ConstructorArgumentValues();
					minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
				}
				else {
					minNrOfArgs = 0;
				}
			}

			LinkedList<UnsatisfiedDependencyException> causes = null;
           // 遍历同名候选方法
			for (Method candidate : candidates) {
             //   获取候选方法的参数列表
				Class<?>[] paramTypes = candidate.getParameterTypes();

				if (paramTypes.length >= minNrOfArgs) {
					ArgumentsHolder argsHolder;
                //在调用getBean方法时传的参数不为空,则工厂方法的参数个数需要与
               // 传入的参数个数严格一致
					if (explicitArgs != null) {
						// Explicit arguments given -> arguments length must match exactly.
						if (paramTypes.length != explicitArgs.length) {
							continue;
						}
						argsHolder = new ArgumentsHolder(explicitArgs);
					}
					else {
						// 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);
							}
                     //当传入的参数为空,需要根据工厂方法的参数类型注入相应的
                   //  bean。详细的注入代码可查看
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
                     //暂不过多解析,如有需要再另外开篇记录
							argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
									paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
						}
						catch (UnsatisfiedDependencyException ex) {
							if (logger.isTraceEnabled()) {
								logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
							}
							// Swallow and try next overloaded factory method.
							if (causes == null) {
								causes = new LinkedList<>();
							}
							causes.add(ex);
							continue;
						}
					}
           /**计算工厂方法的权重,分严格模式和宽松模式,计算方式可以看本文最后的附录
            严格模式会校验子类(注入参数)继承了多少层父类(方法参数)层数越多权重越大,越不匹配
            ,宽松模式,只要是注入参数类型是方法参数类型的子类就行。
            默认宽松模式 在argsHolders中会有arguments和rawArguments,;
           例如在注入bean时,如果有经历过createArgumentArray方法中的TypeConverter
         (如有有定义并且注册到beanFactory中)的,arguments和rawArguments的值是不一样的
           如果没有经过转换,两者是一样的。通过getBean传入的参数两者通常都是一样的
           所以都是先将工厂方法的参数类型与arguments的比较,不同则赋予最大权重值,
           相同则与rawArguments比较,与rawArguments中的相同,就会赋最大权重值-1024,
           不相同,则赋最大权重值-512,经过类型转换一定会执行最大权重值-512的操作。
           权重值越大,该工厂方法越不匹配。总的来说就是传入的参数或者注入的参数类型
           与工厂方法参数类型的比对。**/
					int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
							argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
					// Choose this factory method if it represents the closest match.
					if (typeDiffWeight < minTypeDiffWeight) {
            /**  当权重小时,重新设置factoryMethodToUse 和argsHolderToUse ,argsToUse ,
              并把当前权重值设置为最小权重值,等待遍历的下一个候选工厂方法比对,
              并且将ambiguousFactoryMethods (表示有含糊同样权重的候选方法)设置为空**/
						factoryMethodToUse = candidate;
						argsHolderToUse = argsHolder;
						argsToUse = argsHolder.arguments;
						minTypeDiffWeight = typeDiffWeight;
						ambiguousFactoryMethods = null;
					}
					// Find out about ambiguity: In case of the same type difference weight
					// for methods with the same number of parameters, collect such candidates
					// and eventually raise an ambiguity exception.
					// However, only perform that check in non-lenient constructor resolution mode,
					// and explicitly ignore overridden methods (with the same parameter signature).
           /**  当遍历到下一个候选方法的时候,已经设置了factoryMethodToUse 且权重值
             与上一次的最小权重值相等时,ambiguousFactoryMethods填值,这个ambiguousFactoryMethods不为空
             表示有两个候选方法的最小权重相等,spring无法匹配出最适合的工厂方法,
             如果再继续往下遍历候选器,有更小的权重值,那ambiguousFactoryMethods会
             再次被设置为空**/
					else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
							!mbd.isLenientConstructorResolution() &&
							paramTypes.length == factoryMethodToUse.getParameterCount() &&
							!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
						if (ambiguousFactoryMethods == null) {
							ambiguousFactoryMethods = new LinkedHashSet<>();
							ambiguousFactoryMethods.add(factoryMethodToUse);
						}
						ambiguousFactoryMethods.add(candidate);
					}
				}
			}

			if (factoryMethodToUse == null) {
				if (causes != null) {
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				List<String> argTypes = new ArrayList<>(minNrOfArgs);
				if (explicitArgs != null) {
					for (Object arg : explicitArgs) {
						argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
					}
				}
				else if (resolvedValues != null) {
					Set<ValueHolder> valueHolders = new LinkedHashSet<>(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") + ".");
			}
             //返回类型不能为void
			else if (void.class == factoryMethodToUse.getReturnType()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Invalid factory method '" + mbd.getFactoryMethodName() +
						"': needs to have a non-void return type!");
			}
           //存在含糊的两个工厂方法,不知选哪个
			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);
			}

			if (explicitArgs == null && argsHolderToUse != null) {
				mbd.factoryMethodToIntrospect = factoryMethodToUse;
				argsHolderToUse.storeCache(mbd, factoryMethodToUse);
			}
		}

		Assert.state(argsToUse != null, "Unresolved factory method arguments");
     //   到达这里,恭喜,可以完成实例化了
		bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
		return bw;
	}

看下例子

        @Bean
        public String getStr20(){
            System.out.println("helloTest in HelloConfigurationInner20");
            return "helloTest";
        }
        @Bean
        public Executor  getStr20(Executor executor){
            System.out.println("helloTest in HelloConfigurationInner20");
            return executor;
        }
//        两者参数个数一样多,权重也一样,两者的参数都不是通过转换类型得来的,无法判断哪个才是被选召的孩子
//        @Bean
//        public String getStr20(OrderBean hello){
//            System.out.println("helloTest in HelloConfigurationInner20");
//            return "helloTest"+hello;
//        }
2、autowireConstructor

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor—>org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs)
构造器方法的过程有很多跟工厂方法相似的地方,比如,传入参数的处理,候选方法的排序,参数的注入,权重计算等。不同的是instantiateUsingFactoryMethod有factoryBean的查找,重要的逻辑基本差不多,就不重复记录了,重点说下在调用autowireConstructor前就要先获取到构造器,并作为参数传入,重点来关注spring默认的获取构造方法的逻辑
进入org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance–>org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors遍历所有的SmartInstantiationAwareBeanPostProcessor实例,执行其determineCandidateConstructors方法(如有需要可以自定义SmartInstantiationAwareBeanPostProcessor,按需求重写determineCandidateConstructors方法)默认的processor为AutowiredAnnotationBeanPostProcessor接着进入org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors看关键部分

//如果之前已经有用构造方法实例化bean,就会有缓存,原型模式和scope模式会有再次使用的时候
		// Quick check on the concurrent map first, with minimal locking.
		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		if (candidateConstructors == null) {
			// Fully synchronized resolution now...
			synchronized (this.candidateConstructorsCache) {
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				if (candidateConstructors == null) {
					Constructor<?>[] rawCandidates;
					try {
//缓存中不存在的时候使用getDeclaredConstructors方法获取所有的构造方法
						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);
					Constructor<?> requiredConstructor = null;
					Constructor<?> defaultConstructor = null;
//优先的构造方法是从kotlin文件获取,没玩过kotlin,不知道怎么弄,先不管
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					int nonSyntheticConstructors = 0;
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
//查找是否有@Autowired注解
						AnnotationAttributes ann = findAutowiredAnnotation(candidate);
						if (ann == null) {
//如果没有@Autowired注解,查找父类的构造方法有没有@Autowired注解
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						if (ann != null) {
            //  当@Autowired注解的构造方法不止一个,那上一次处理的候选构造方法
         //     已经设置到requiredConstructor 中,那么第二个@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);
								}
//第一个处理的有@autowired处理的构造方法设置requiredConstructor ,并设置到candidates中
								requiredConstructor = candidate;
							}
							candidates.add(candidate);
						}
//当构造方法没有@Autowired注解且参数个数为0,选为defaultConstructor 
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
//往候选方法中加入defaultConstructor
//(好像requiredConstructor 为null,candidates就会为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));
							}
						}
//候选方法不为空的时候进入此处,此时就一个@Autowired注解的构造方法
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
//当获取的所有构造方法只有一个,且不是@autowired注解的(注解的在上面处理了)
//且参数在一个以上,该方法作为候选的构造方法
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
//后面primaryConstructor 的都不看了
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					else {
						candidateConstructors = new Constructor<?>[0];
					}
//缓存选定的候选构造方法,供原型模式和scope模式第二次实例化时使用
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
返回选定的构造函数列表
		return (candidateConstructors.length > 0 ? candidateConstructors : null);

上demo

/**首先永远不必理会无参构造方法,他最后都是不会通过autowireConstructor方法实例化,
如果只有一个带参构造方法,那他就被选择为候选构造方法,如果有多个带参构造方法,
则需要通过@Autowired注解其中一个,不能有多个@Autowired注解的构造方法**/

  //  public TestService(){}
//    @Autowired
    public TestService(OrderBean orderBean) {
        this.orderBean = orderBean;
    }


//    @Autowired
//    public TestService(Executor executor,OrderBean orderBean){}


关于权重值的计算

关于候选方法排序

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值