- 原理分析
- 原码分析一determineCandidateConstructors
- 原码分析一autowireConstructor
- 总结
determineCandidateConstructors
- 1 遍历所有的构造方法,如果有Autowired(required=true)的构造函数且只有一个返回该构造函数
- 2遍历所有的构造方法,如果有Autowired(required=true)的构造函数且有多个,报错
- 3 如果有多个注解标注的构造函数,则返回所有注解标注的外加无参构造
- 4 如果只有一个构造函数返回该构造函数
- 5 其他情况返回null
autowireConstructor
- 将所有的候选构造函数排序,排序规则[第一排序规则: public方法优先,第二排序规则:参数数量降序]
- 设置一个算法,输入构造函数,输出一个整数
- 判断构造方法能否完成依赖注入,不能跳过该构造函数
- 算法输出的最小值则作为被选中的构造函数
- 通过选中的构造函数完成对象实例化
- 算法根据mbd.isLenientConstructorResolution(默认宽松模式)区分严格模式和宽松模式,不同的模式有不同计算方式
| 有注解优先注解 无注解只有一个构造函数则明确 其他不明确后置处理 |
|---|
**
* 说明: 一套选择机制选择一个构造函数用于构建Object
* 但是如果找到多个就返回多个 因为无法抉择 交给后续处理autowireConstructor方法处理【sortConstructor 构造之后的那个构造创建处理 public优先 参数数量大的优先】
*
*
* 选择逻辑
* 1 autowired注解request为true的构造函数有多个,报错
* 2 autowired注解request为true的构造函数有一个,返回该构造函数
* 3 autowired注解request为false的构造函数有多个,返回该构造函数集合+无参构造
* 4 只有一个构造函数 返回该构造函数[可能有注解 可能是多参数 也可能是无参构造]
* 5 存在多个构造函数 返回null【其无法决定】
*
* @param beanClass
* @param beanName
* @return
* @throws BeanCreationException
*
@Override
@Nullable
public Constructor>[] determineCandidateConstructors(Class> beanClass, final String beanName)
throws BeanCreationException {
...... 删除@lookup改变的mbd的methodOverrides处理代码
...... 删除缓存相关
if (candidateConstructors == null) {
step-1: 获取所有的构造方法作为原始的构造器集合
Constructor>[] rawCandidates = beanClass.getDeclaredConstructors();
List> candidates = new ArrayList<>(rawCandidates.length);
@Authwired(required = true)的构造函数
Constructor> requiredConstructor = null;
无参构造函数
Constructor> defaultConstructor = null;
采用Kotlin建立的构造函数 这种已经不是java语言了;一般primaryConstructor为null 自行了解Kotlin 相关{现在的JVM支持的不只java一种语言}
Constructor> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
非混合构造函数
int nonSyntheticConstructors = 0;
step-2: 循环处理所有的构造方法
for (Constructor> candidate : rawCandidates) {
判断当前的构造方法,属性,类,方法是不是混合类
if (!candidate.isSynthetic()) { //
nonSyntheticConstructors++; // +1表示构造方法可用
}
else if (primaryConstructor != null) {
continue;
}
step-3 找 @Value 和@Autowired @Inject 标注的构造方法 [ AnnotationAttribute是这些注解的属性和值]
AnnotationAttributes ann = findAutowiredAnnotation(candidate);
......删除找父类构造的过程
step: 3-1 找到了并且注解的required属性为true加入候选者集合
if (ann != null) {
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) {
如果存在多个必要候选者 比如两个@autowired(request=true) 标注的构造方法 则会抛出异常
if (!candidates.isEmpty()) {
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) {
step-4 没有注解并且参数为0 设为无参构造
defaultConstructor = candidate;
}
}
candidates不为空 返回所有选择到的构造函数外加无参构造函数
if (!candidates.isEmpty()) {
if (requiredConstructor == null) {
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
}
}
candidateConstructors = candidates.toArray(new Constructor>[0]);
}
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
没有@autowired等注解标注 且一共只有一个构造函数 返回该构造函数
candidateConstructors = new Constructor>[] {rawCandidates[0]};
}
删除kotlin语言相关
else {
其他情况一律不加考虑 依赖下游自行决定选择何种构造函数 下游实际通过排序sortConstructor完成多个构造函数的选择
candidateConstructors = new Constructor>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
返回一个说明后面会选择 存在多个这个返回null 交给autowireConstructor方法自行选择
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
原码分析一autowireConstructor
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor>[] chosenCtors, @Nullable Object[] explicitArgs) {
......删除大量其他代码以方便理解
BeanWrapperImpl bw = new BeanWrapperImpl();
step-1 对所有的构造函数排序 按照访问限制修饰符进行排序public优先 按照方法参数进行排序,数量多的优先
AutowireUtils.sortConstructors(candidates);
step-2 开始算法计算:
算法minTypeDiffWeight的初始值
int minTypeDiffWeight = Integer.MAX_VALUE;
for (Constructor> candidate : candidates) {
step-2.1 如果寻找构造注入的参数报错则跳过改构造函数
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
try {
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
如果寻找构造注入的参数报错则跳过改构造函数
continue;
}
}
step-2.2 设计一种算法计算typeDiffWeight的值,所有的构造函数中typeDiffWeight最小的值为被选中的构造函数
- 如果typeDiffWeight都相同 则按照排序的规则选中第一个构造函数
- 算法依据isLenientConstructorResolution区分严格模式还是宽松模式 默认宽松模式
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
if (typeDiffWeight < minTypeDiffWeight) {
step-2.3 如果当前typeDiffWeight小于minTypeDiffWeight则更新minTypeDiffWeight
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
}
step-3 实例化对象
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
总结
- 分析了如何选择分区构造函数 determineCandidateConstructors
- 分析了存在多个构造函数如何通过算法实现构造的选择 排序 + 算法
- 算法细节并未讲解 大家可以看方法说明



