每天一点点,Spring得到当前类的候选构造方法

184 阅读2分钟

当Spring中 有多个构造函数的时候,是如何得到候选的构造方法

AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors

其中主要的是 AutowiredAnnotationBeanPostProcessor 这个类

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors 得到候选的构造方法

1、找存在@Lookup注解的方法

1、先从缓存中判断当前bean是否找过 AutowiredAnnotationBeanPostProcessor#lookupMethodsChecked

private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

2、没有找过执行查找 3、如果存在添加到当前BeanDefinition的#methodOverrides中

2、 找当前bean的候选构造方法

1、先从缓存中判断当前bean是否找过 AutowiredAnnotationBeanPostProcessor#candidateConstructorsCache

private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);

2、如果没有执行查找

1、得到当前bean对象的所有构造函数
rawCandidates = beanClass.getDeclaredConstructors();
2、定义四个变量
// 所有候选的构造函数
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
// @Autowired#required = true的构造方法
Constructor<?> requiredConstructor = null;
//默认的无参构造
Constructor<?> defaultConstructor = null;
// 可忽略 kotlin
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
3、遍历当前bean的所有候选构造函数

1、判断当前构造函数是否有@Autowired注解 2、判断当前类是不是CGLIB生成的代理类(CGLIB_CLASS_SEPARATOR),如果是在判断被代理类的相同参数的构造函数是否有@Autowired注解 3、判断当前构造方法上面是否存在@Autowired注解 3.1、如果已经存在了一个加了@Autowired,且@Autowired#required = true的构造方法,抛出异常 3.1.1 一个类的构造函数中只能有 一个 @Autowired(required=true) 的注解

if (requiredConstructor != null) {
	throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
}

3.2、得到当前构造方法的@Autowired注解的required值

boolean required = determineRequiredStatus(ann);

3.3、如果 required == true,需要判断当前候选的构造函数集合是否为空,如果不为空抛出异常,

//  一个类的构造函数中只能有 一个 @Autowired(required=true) 的注解
if (requiredConstructor != null) {
	throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
}

3.4、设置 ① requiredConstructor = 当前构造函数②添加当前构造函数到候选构造函数集合中

requiredConstructor = candidate;
candidates.add(candidate);

4、如果是默认构造函数,记录默认构造函数

else if (candidate.getParameterCount() == 0) {
	defaultConstructor = candidate;
}

5、如果当前类没有无参构造,且所有构造函数都没有加@Autowired注解,此时,候选的构造函数集合为空 candidates.isEmpty() = trure ;

6、如果候选的构造函数集合 candidates 不为空 6.1、当前类如果不存在加了@Autowired且required=true的类,并且无参构造函数存在,往候选的构造函数中添加无参构造函数;

if (!candidates.isEmpty()) {
	if (requiredConstructor == null) {
		if (defaultConstructor != null) {
				candidates.add(defaultConstructor);
		}
	}
	candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}

7、如果当前类只有一个构造函数,且不是无参构造,候选数组中只有一个元素==> 当前这个构造函数

else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
	candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}

8、如果当前类只存在有参构造,但是所有的有参构造都没有加@Autowired注解,此时,候选的构造函数集合为空 candidates.isEmpty() = trure ;返回候选集合为 空的数组

else {
	candidateConstructors = new Constructor<?>[0];
}

9、放入缓存中

this.candidateConstructorsCache.put(beanClass, candidateConstructors);