当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);