【Spring源码分析】推断构造方法

推断构造方法源码解析

  • 一、确认候选构造——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors
  • 二、autowireConstructor 方法源码解析
  • 三、总结

阅读此需阅读下面这些博客先
【Spring源码分析】Bean的元数据和一些Spring的工具
【Spring源码分析】BeanFactory系列接口解读
【Spring源码分析】执行流程之非懒加载单例Bean的实例化逻辑
【Spring源码分析】从源码角度去熟悉依赖注入(一)
【Spring源码分析】从源码角度去熟悉依赖注入(二)
【Spring源码分析】@Resource注入的源码解析
【Spring源码分析】循环依赖的底层源码剖析

Spring 在推断构造方法的逻辑上面写的实在太复杂了,构造种类贼多贼多,恕我实力有限,这里的话算不上源码分析,只能说是原理吧,这我只考虑了平常开发会遇到的,什么getBean去添加参数的、BeanDefinition去填充的我都一概跳过,看不懂一点(比如多参构造参数相同的情况下(@Autowired注解修饰后的required为false)会进行评分操作,有点复杂,感觉遇不着就不想研究了)。

(这篇博客可能有点水了)

【Spring源码分析】推断构造方法_第1张图片

一、确认候选构造——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors

确认候选的构造也是通过 BeanPostProcessor 来进行的(SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors),引进的代码如下:

		// Candidate constructors for autowiring?
		// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
		// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

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

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

Spring 实现的 SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors 方法中就一个对其进行实现了——AutowireAnnotationBeanPostProcessor。

下面俺对其核心代码进行解析:

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

		// 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 {
						// 拿到所有的构造方法
						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);

					// 用来记录required为true的构造方法,一个类中只能有一个required为true的构造方法
					Constructor<?> requiredConstructor = null;
					// 用来记录默认无参的构造方法
					Constructor<?> defaultConstructor = null;

					// 遍历每个构造方法
					for (Constructor<?> candidate : rawCandidates) {

						// 当前遍历的构造方法是否写了@Autowired
						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);

						// 当前构造方法上加了@Autowired
						if (ann != null) {
							// 整个类中如果有一个required为true的构造方法,那就不能有其他的加了@Autowired的构造方法
							// 若存在required为true的还存在其他的@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);
								}
								// 记录唯一一个required为true的构造方法
								requiredConstructor = candidate;
							}
							// 记录所有加了@Autowired的构造方法,不管required是true还是false
							// 如果默认无参的构造方法上也加了@Autowired,那么也会加到candidates中
							candidates.add(candidate);

							// 从上面代码可以得到一个结论,在一个类中,要么只能有一个required为true的构造方法,要么只能有一个或多个required为false的方法
						} else if (candidate.getParameterCount() == 0) {
							// 记录唯一一个无参的构造方法
							defaultConstructor = candidate;
						}

						// 有可能存在有参、并且没有添加@Autowired的构造方法
					}


					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						// 如果不存在一个required为true的构造方法,则所有required为false的构造方法和无参构造方法都是合格的
						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));
							}
						}
						// 如果只存在一个required为true的构造方法,那就只有这一个是合格的
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
					// 没有添加了@Autowired注解的构造方法,并且类中只有一个构造方法,并且是有参的
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[]{rawCandidates[0]};
					}
					 else {
						// 如果有多个有参、并且没有添加@Autowired的构造方法,是会返回空的
						candidateConstructors = new Constructor<?>[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}

【Spring源码分析】推断构造方法_第2张图片
就是说只有三种情况有可用的构造(这里是指会有返回的候选构造方法):

  • 使用了 @Autowired 注解,有且只有一个 required 为 true;
  • 使用了 @Autowired 注解,required 都为 false;
  • 没有使用 @Autowired 注解,有且只有一个多参构造。

【Spring源码分析】推断构造方法_第3张图片通过这些代码的解析可以知道:

  • 含有多个参数多个构造和只有一个无参的都会走 instantiateBean 的逻辑,去通过无参构造去实例化,如果没有的话就抛异常咯,换句话说就是没用@Autowired注解就是去找无参,没有就抛异常
    • 【Spring源码分析】推断构造方法_第4张图片
    • 【Spring源码分析】推断构造方法_第5张图片
  • 有且只有一个 @Autowired 注解且required为true,有多个 @Autowired 注解,但是 required 都为 false,那么就是通过 autowireConstructor 方法去实现 Spring 的自动构造。

二、autowireConstructor 方法源码解析

太难了,看不了一点,直接阐述源码流程(和上面的接着的)。

上面确认候选构造的时候还有三种情况我们需要考虑:

  • 使用了 @Autowired 注解,有且只有一个 required 为 true;
  • 使用了 @Autowired 注解,required 都为 false;
  • 没有使用 @Autowired 注解,有且只有一个多参构造。

也就是上面这三种情况会进入到 autowireConstructor 方法。
下面阐述一下流程:

  1. 首先是对构造进行个排序,以参数的个数降序排序,就是参数个数多的在前面:
    • 【Spring源码分析】推断构造方法_第6张图片
  2. 然后去调用 beanFactory#resolveDependency 方法去给参数进行填充参数;
  3. 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的
    • 【Spring源码分析】推断构造方法_第7张图片
    • 【Spring源码分析】推断构造方法_第8张图片
      也就是说构造方法要满足可用的话,必须所有的参数都是Spring容器中拥有的,可以注入的。

三、总结

本篇并不是Spring所有推断构造方法的逻辑,只是其中的一部分——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors 中推断出来的构造方法是怎么处理的。

主要就是有无 @Autowired 注解俩各方面。

【Spring源码分析】推断构造方法_第9张图片当有多个构造 @Autowired 注解,但是 required 都为 false 的话,考虑 autowireConstructor 的逻辑。先是将所候选的构造参数个数降序排序,然后逐个去匹配,看看参数是否都能在容器中找到,找不到就换下一个,找到就用该构造。

你可能感兴趣的:(Java源码分析,spring,java,数据库)