Spring 构造推断源码浅析1

215 阅读4分钟

AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 获取class
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
//对于工厂方法的处理,其实就是  @Bean 的处理
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// 表示是否已经推断过构造方法
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
            //如果bd已经存在构造方法,resolved设置为true,表示已经存在构造方法,不需要进行推断
            //只有原型模式才会进来这里
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
                    //在推断构造方法的时候,会设置 constructorArgumentsResolved = true
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
        //如果bd已经有构造方法了,也就是原型就会直接通过已有的构造方法进行反射
		if (resolved) {
        //表示使用 autowireConstructor 推断过构造方法
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
            //无参构造
				return instantiateBean(beanName, mbd);
			}
		}

		// 进行第一次构造推断
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        //1.第一次推断的构造方法不为空
        //2.自动注入模式为构造注入
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
                //第二次推断构造
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}
		//使用无参构造反射
		return instantiateBean(beanName, mbd);
	}

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
			throws BeanCreationException {
//..... 忽略对  @Lookup 注解的解析 
		// candidateConstructors 缓存推断完的构造方法,但是感觉作用不大
        //因为如果是单例的话,这个方法只会走一次,如果是原型模式,那也不会走这个
        //原型模式会从 beandefinition 中获取构造方法
		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;
                    //这个正常是为null,可以不用管
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					int nonSyntheticConstructors = 0;
                    //遍历所有的构造方法
					for (Constructor<?> candidate : rawCandidates) {
                    //这种情况一般是内部类,正常情况不是内部类,所以不用管
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
                        //找到构造方法上面加的  @Atowired @alue
						AnnotationAttributes ann = findAutowiredAnnotation(candidate);
						if (ann == null) {
                        //如果没有加注解,会去对比 userClass跟 beanClass ,这个不知道啥场景
                      //会不想等,正常情况是相等的
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
//.....
							}
						}
                        //有加注解的情况
						if (ann != null) {
                        // 如果  requiredConstructor 已经有了,就会报错
                        //因为此时存在多个加注解的构造方法,这样spring就不知道要选哪个,只好报错
							if (requiredConstructor != null) {
					//.....
							}
                            //获取 注解 的  required  属性
							boolean required = determineRequiredStatus(ann);
                            //如果  required = true(表示必须要用这个构造
							if (required) {
                            //候选的构造函数列表不为空,此时就会报错
								if (!candidates.isEmpty()) {
//......报错
								}
                                //设置注解构造为 当前构造方法
								requiredConstructor = candidate;
							}
                            //往候选构造列表添加当前构造方法
							candidates.add(candidate);
						}
                        //如果 没有构造方法没有添加注解,而且构造方法的入参个数=0,也就是无参方法
                        //设置默认构造方法为无参的构造方法
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
                    //上面大体就是寻找加注解的构造方法,如果有加注解的构造方法,就添加到 candidates
                    //如果有加注解的构造方法而且是必须的,就设置到 requiredConstructor
                    //如果存在多个必须的注解构造方法就会报错
                    //有默认构造方法,就设置到 defaultConstructor
                    //如果有注解必须的同时有注解非必须的构造方法,也会报错
                    
                    //如果候选的构造方法不为空
					if (!candidates.isEmpty()) {
                    //如果 requiredConstructor 不为空,而且默认构造不为空
                    //就把默认构造放到 candidates 集合中,这种情况只有在注解require = false的情况
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
						}
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
                    //如果候选构造为空,就是没有添加注解,rawCandidates 是所有的构造方法
                    //rawCandidates 只有一个构造方法,而且构造方法的参数大于一,那就是用这个构造方法
					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};
					}
                    //这个也不开 primaryConstructor 为空
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					else {
                    //找不到合适的构造方法
						candidateConstructors = new Constructor<?>[0];
					}
                    //将推断出来的构造放到缓存中
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
        //如果推断的构造方法数量为空,那就返回 null
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}


构造推断流程图:

最后结果

  • 1.不加注解,只有一个默认构造:返回null

  • 2.不加注解,多个构造,返回null

  • 3.不加注解,只有一个构造,非无参构造,返回这个

  • 4.加注解 required都为 false,返回这几个require = false的构造

  • 5.加注解,多个required为 true 报错

  • 6.加注解,一个requred=true,多个require=false,报错

  • 7.加注解,一个require=ture,没有默认构造返回这个require=true

  • 8.加注解,一个require=true,有默认构造的返回默认构造+require=ture

  • 9.所以有返回值的情况是3,4,7,8。要么没有注解只有一个有参构造,要么加注解,加的注解要么一个requre=ture,要么都是require=false。