23、Spring5.x源码之旅二十三getBean详解九之寻找构造方法

  • determineConstructorsFromBeanPostProcessors
    • AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors

determineConstructorsFromBeanPostProcessors

前面讲了工厂方法的实例化,现在可以讲一般的构造方法实例化了,首先会进行处理器处理,找出合适的构造方法:

@Nullable
	protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
			throws BeansException {
   
     

		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
   
     
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
   
     
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
   
     
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
					if (ctors != null) {
   
     
						return ctors;
					}
				}
			}
		}
		return null;
	}

AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors

主要是这个处理器做的事,开始检查Lookup注解,然后处理,添加方法覆盖。主要还是后面的构造函数获取,首先获取缓存,如果没有的话就获取所有的构造函数,然后每个构造函数都进行遍历,获取注解,如果为空的话,判断是不是代理类,是的话就获取父类,也就是我们自己定义的类,再次获取注解。如果注解存在,就看Autowiredrequired属性,如果有多个是true或者有一个是true,其他是false都会报错,因为他没办法知道该用哪个,如果全是false,那是可以的。如果只有一个false,会报一个警告。如果有Autowired注解的,就优先注解的构造方法,如果没有,就只有一个构造方法且有参数的优先,然后是有优先构造方法,跟Kotlin有关,所以基本不会优先,然后剩下的就是默认构造方法了。注意如果有多个有参构造方法其实他也不知道要用哪个,实例化的时候会去找默认构造方法,但是没找到,会报异常。

@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
			throws BeanCreationException {
   
     

		// 查找lookup
		if (!this.lookupMethodsChecked.contains(beanName)) {
   
     
			if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
   
     
				try {
   
     
					Class<?> targetClass = beanClass;
					do {
   
     //遍历当前类以及所有父类,找出Lookup注解的方法进行处理
						ReflectionUtils.doWithLocalMethods(targetClass, method -> {
   
     
							Lookup lookup = method.getAnnotation(Lookup.class);
							if (lookup != null) {
   
     
								Assert.state(this.beanFactory != null, "No BeanFactory available");
								LookupOverride override = new LookupOverride(method, lookup.value());
								try {
   
     
									RootBeanDefinition mbd = (RootBeanDefinition)
											this.beanFactory.getMergedBeanDefinition(beanName);
									mbd.getMethodOverrides().addOverride(override);
								}
								catch (NoSuchBeanDefinitionException ex) {
   
     
									throw new BeanCreationException(beanName,
											"Cannot apply @Lookup to beans without corresponding bean definition");
								}
							}
						});
						targetClass = targetClass.getSuperclass();
					}
					while (targetClass != null && targetClass != Object.class);//遍历父类,直到Object

				}
				catch (IllegalStateException ex) {
   
     
					throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
				}
			}
			this.lookupMethodsChecked.add(beanName);//已经检查过
		}

		//先检查一遍缓存
		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 {
   
     
						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;//默认构造方法
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);//优先的构造方法,Kotlin的类才有,一般都是空
					int nonSyntheticConstructors = 0;
					for (Constructor<?> candidate : rawCandidates) {
   
     
						if (!candidate.isSynthetic()) {
   
     //非合成的方法
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
   
     
							continue;
						}
						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);//寻找Autowired和value的注解
						if (ann == null) {
   
     
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
   
     //如果是有代理的,找到被代理类
								try {
   
     
									Constructor<?> superCtor =//获取构造方法
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);//继续寻找Autowired和value的注解
								}
								catch (NoSuchMethodException ex) {
   
     
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						if (ann != null) {
   
     
							if (requiredConstructor != null) {
   
     //有两个Autowired注解,冲突了
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							boolean required = determineRequiredStatus(ann);//是否需要,默认是true
							if (required) {
   
     
								if (!candidates.isEmpty()) {
   
     //如果已经有required=false了,又来了一个required=true的方法就报异常了,这样两个可能就不知道用哪个了
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								requiredConstructor = candidate;
							}
							candidates.add(candidate);//加入集合
						}
						else if (candidate.getParameterCount() == 0) {
   
     //是无参构造方法
							defaultConstructor = candidate;
						}
					}
					if (!candidates.isEmpty()) {
   
     //如果候选不为空,基本就是有Autowired注解的,转换成数组直接返回
						// Add default constructor to list of optional constructors, as fallback.
						if (requiredConstructor == null) {
   
     
							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));
							}
						}
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
   
     
						candidateConstructors = new Constructor<?>[] {
   
     rawCandidates[0]};//只有一个函数且有参数
					}
					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 {
   
     //大于2个没注解的构造方法就不知道要用什么了,所以就返回null
						candidateConstructors = new Constructor<?>[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}

总结下就是:

  • 如果有多个Autowired,required有true,不管有没有默认构造方法,会报异常。
  • 如果只有一个Autowired,required是false,没有默认构造方法,会报警告。
  • 如果没有Autowired注解,定义了2个及以上有参数的构造方法,没有无参构造方法,就会报错。
  • 其他情况都可以,但是以有Autowired的构造方法优先,然后才是默认构造方法。

如果构造方法存在且是有参数的,那就会调用autowireConstructor进行自动装配,如果不存在基本上无参构造方法了,除非有Kotlin提供优先构造方法。后面来讲自动装配和默认构造方法怎么实例化吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。