前言
上一篇文章中介绍到,AbstractAutowireCapableBeanFactory类的createBeanInstance方法,是创建BeanWrapper的方法,BeanWrapper主要包含bean实例、Class对象和相关属性。
1 obtainFromSupplier方法
我们按照顺序,先一起看看obtainFromSupplier方法中,到底做了一些什么事情:
这个方法逻辑比较清晰,先往currentlyCreatedBean这个ThreadLocal中设置beanName,然后调用supplier.get()方法,回调获取bean实例。
如果已经存在outerBean,则往currentlyCreatedBean设置这个currentlyCreatedBean。否则,清除currentlyCreatedBean。
如果supplier.get()方法返回的bean实例为空,则创建一个空bean对象。
然后new一个BeanWrapperImpl实例。
最后初始化BeanWrapperImpl实例。
这个方法只做了两件事:
- 设置了一个类型转换服务。
- 注册了属性编辑器。
这两个功能还是非常有用的,后面给大家专题讲解。
2 autowireConstructor方法
其实在AbstractAutowireCapableBeanFactory类的createBeanInstance方法中,autowireConstructor方法调用的频率是非常高,这个方法非常重要。
这个方法中只有一行代码,调用了ConstructorResolver类的autowireConstructor方法。
publicBeanWrapperautowireConstructor(StringbeanName,RootBeanDefinitionmbd,
@NullableConstructor<?>[]chosenCtors,@NullableObject[]explicitArgs){
//直接new了一个BeanWrapperImpl对象
BeanWrapperImplbw=newBeanWrapperImpl();
//初始化参数编辑器
this.beanFactory.initBeanWrapper(bw);
//真正创建bean的构造器
Constructor<?>constructorToUse=null;
//创建bean时使用的参数
ArgumentsHolderargsHolderToUse=null;
//创建bean是使用参数对应的值
Object[]argsToUse=null;
//如果getBean方法传入的构造器参数不为空,则使用传入的构造器参数
if(explicitArgs!=null){
argsToUse=explicitArgs;
}
else{
//已解析的构造参数
Object[]argsToResolve=null;
synchronized(mbd.constructorArgumentLock){
//获取缓存中的构造器或者工厂方法
constructorToUse=(Constructor<?>)mbd.resolvedConstructorOrFactoryMethod;
//如果缓存中的构造器或工厂方法不为空,并且已解析构造器参数状态为true
if(constructorToUse!=null&&mbd.constructorArgumentsResolved){
//直接使用缓存中的已解析的构造器参数
argsToUse=mbd.resolvedConstructorArguments;
//如果该参数还是为空
if(argsToUse==null){
//从准备用于解析的构造器参数中获取数据
//当constructorArgumentsResolved为true时,resolvedConstructorArguments和preparedConstructorArguments至少有一个缓存了构造器的参数
argsToResolve=mbd.preparedConstructorArguments;
}
}
}
//如果已解析的构造器参数不为空
if(argsToResolve!=null){
//解析构造器参数,比如:将User("123","1")转换成User(123,1)
argsToUse=resolvePreparedArguments(beanName,mbd,bw,constructorToUse,argsToResolve);
}
}
//如果缓存中没有构造器或构造器参数,需要确定构造器中的候选者
if(constructorToUse==null||argsToUse==null){
//指定要推断的构造器,如果传入的chosenCtors不为空,则用它作为候选者
Constructor<?>[]candidates=chosenCtors;
//如果候选者构造器为空
if(candidates==null){
//获取bean的Class
Class<?>beanClass=mbd.getBeanClass();
try{
//如果不允许访问非public的构造器,则返回所有构造器,否则返回public的构造器
candidates=(mbd.isNonPublicAccessAllowed()?
beanClass.getDeclaredConstructors():beanClass.getConstructors());
}
catch(Throwableex){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"ResolutionofdeclaredconstructorsonbeanClass["+beanClass.getName()+
"]fromClassLoader["+beanClass.getClassLoader()+"]failed",ex);
}
}
//如果只有一个候选者构造器,并且传入的构造器参数为空,并且构造器是无参数的
if(candidates.length==1&&explicitArgs==null&&!mbd.hasConstructorArgumentValues()){
//获取这个唯一的构造器
Constructor<?>uniqueCandidate=candidates[0];
//如果该构造器参数为空
if(uniqueCandidate.getParameterCount()==0){
//加锁
synchronized(mbd.constructorArgumentLock){
//将构造器设置到缓存中
mbd.resolvedConstructorOrFactoryMethod=uniqueCandidate;
//设置已解析构造器参数状态为true
mbd.constructorArgumentsResolved=true;
//设置已解析构造器参数为空对象
mbd.resolvedConstructorArguments=EMPTY_ARGS;
}
//使用无参构造器创建bean实例
bw.setBeanInstance(instantiate(beanName,mbd,uniqueCandidate,EMPTY_ARGS));
//返回BeanWrapperImpl对象
returnbw;
}
}
//是否需要自动装配
//chosenCtors不为空或者autowireMode为AUTOWIRE_CONSTRUCTOR时,需要自动装配
//当构造器通过@Autowired注解修饰时,是需要字段装配的
booleanautowiring=(chosenCtors!=null||
mbd.getResolvedAutowireMode()==AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValuesresolvedValues=null;
//构造器参数个数
intminNrOfArgs;
//当getBean方法传入的构造器参数不为空时
if(explicitArgs!=null){
//使用传入的构造器参数个数作为minNrOfArgs的个数
minNrOfArgs=explicitArgs.length;
}
else{
//获取BeanDefintion中配置的构造器参数对象
ConstructorArgumentValuescargs=mbd.getConstructorArgumentValues();
//创建一个已解析后的构造器参数对象
resolvedValues=newConstructorArgumentValues();
//解析BeanDefintion中构造器参数,返回参数个数
minNrOfArgs=resolveConstructorArguments(beanName,mbd,bw,cargs,resolvedValues);
}
//对候选的构造器集合进行排序
//1.将public排在前面,非public排在后面
//2.将构造器参数个数多的排在前面,少的排在后面
AutowireUtils.sortConstructors(candidates);
//最小匹配差异权重,值越小,越接近我们所需要的目标构造器
intminTypeDiffWeight=Integer.MAX_VALUE;
Set<Constructor<?>>ambiguousConstructors=null;
Deque<UnsatisfiedDependencyException>causes=null;
//遍历所有的候选构造器,找出最符合要求的一个构造器
for(Constructor<?>candidate:candidates){
//获取候选构造器的参数个数
intparameterCount=candidate.getParameterCount();
//如果之前已经找到构造器和参数,并且参数个数比候选者构造器中参数要多时,则直接退出当前循环,不用再找了
if(constructorToUse!=null&&argsToUse!=null&&argsToUse.length>parameterCount){
break;
}
//如果候选者构造器参数个数小于我们需要的构造器个数,则直接略过,寻找下一个
if(parameterCount<minNrOfArgs){
continue;
}
ArgumentsHolderargsHolder;
//获取参数类型
Class<?>[]paramTypes=candidate.getParameterTypes();
//如果没有通过getBean方法指定参数,则resolvedValues不为空
if(resolvedValues!=null){
try{
//获取当前候选者构造器的参数名
//主要是获取ConstructorProperties注解定义的参数名
String[]paramNames=ConstructorPropertiesChecker.evaluate(candidate,parameterCount);
//如果参数名为空
if(paramNames==null){
//则获取ParameterNameDiscoverer
ParameterNameDiscovererpnd=this.beanFactory.getParameterNameDiscoverer();
if(pnd!=null){
//通过ParameterNameDiscoverer获取参数名
paramNames=pnd.getParameterNames(candidate);
}
}
//通过参数名和参数类型解析构造器获取工厂方法所需要的参数,封装到一些数组中,方便后面好调用
argsHolder=createArgumentArray(beanName,mbd,resolvedValues,bw,paramTypes,paramNames,
getUserDeclaredConstructor(candidate),autowiring,candidates.length==1);
}
catch(UnsatisfiedDependencyExceptionex){
if(logger.isTraceEnabled()){
logger.trace("Ignoringconstructor["+candidate+"]ofbean'"+beanName+"':"+ex);
}
if(causes==null){
causes=newArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
else{
//resolvedValues为空,则explicitArgs不为空,说明getBean方法传入了参数
//如果当前候选者构造器参数个数,不等于传入的参数个数,则直接忽略,寻找下一个候选者构造器
if(parameterCount!=explicitArgs.length){
continue;
}
//如果找到了合适的候选者构造器,则创建ArgumentsHolder,把传入的参数封装到这个对象中,方便后面好调用
argsHolder=newArgumentsHolder(explicitArgs);
}
//根据参数类型计算一个匹配差异权重
//区分lenientConstructorResolution是严格模式,还是宽松模式,计算方法不一样。默认是严格模式。
inttypeDiffWeight=(mbd.isLenientConstructorResolution()?
argsHolder.getTypeDifferenceWeight(paramTypes):argsHolder.getAssignabilityWeight(paramTypes));
//如果当前匹配差异权重小于最小匹配差异权重,则认为匹配上了,typeDiffWeight值越小越匹配
if(typeDiffWeight<minTypeDiffWeight){
constructorToUse=candidate;
argsHolderToUse=argsHolder;
argsToUse=argsHolder.arguments;
//重新设置小匹配差异权重
minTypeDiffWeight=typeDiffWeight;
//情况这个不明确的候选者构造器集合
ambiguousConstructors=null;
}
//如果当前匹配差异权重等于最小匹配差异权重,说明可能存在匹配差异权重相同的候选者构造器
elseif(constructorToUse!=null&&typeDiffWeight==minTypeDiffWeight){
//将匹配差异权重相同的候选者构造器添加到,这个不明确的候选者构造器集合ambiguousConstructors中
if(ambiguousConstructors==null){
ambiguousConstructors=newLinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//如果遍历完了,还是没有找到一个合适的候选者构造器,则抛异常
if(constructorToUse==null){
if(causes!=null){
UnsatisfiedDependencyExceptionex=causes.removeLast();
for(Exceptioncause:causes){
this.beanFactory.onSuppressedException(cause);
}
throwex;
}
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Couldnotresolvematchingconstructoronbeanclass["+mbd.getBeanClassName()+"]"+
"(hint:specifyindex/type/nameargumentsforsimpleparameterstoavoidtypeambiguities)");
}
elseif(ambiguousConstructors!=null&&!mbd.isLenientConstructorResolution()){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Ambiguousconstructormatchesfoundonbeanclass["+mbd.getBeanClassName()+"]"+
"(hint:specifyindex/type/nameargumentsforsimpleparameterstoavoidtypeambiguities):"+
ambiguousConstructors);
}
//如果getBean方法没有传入参数,并且解析出的构造器或参数,则加入缓存中
if(explicitArgs==null&&argsHolderToUse!=null){
argsHolderToUse.storeCache(mbd,constructorToUse);
}
}
Assert.state(argsToUse!=null,"Unresolvedconstructorarguments");
//根据找到的构造器和参数创建bean实例
bw.setBeanInstance(instantiate(beanName,mbd,constructorToUse,argsToUse));
//返回BeanWrapperImpl对象
returnbw;
}这个方法的逻辑很多,有些复杂,我下面用一张图,把核心逻辑给大家梳理一下。
此外,如果循环遍历之后,没有找到合适的构造器,或者找出了多个匹配差异权重相同的构造器,都会抛出异常。
3 resolveConstructorArguments方法
接下来,我们一起看看resolveConstructorArguments方法是如何解析构造器中的参数的:
privateintresolveConstructorArguments(StringbeanName,RootBeanDefinitionmbd,BeanWrapperbw,
ConstructorArgumentValuescargs,ConstructorArgumentValuesresolvedValues){
//获取用户自定义的类型转换器
TypeConvertercustomConverter=this.beanFactory.getCustomTypeConverter();
//如果用户自定义的类型转换器不为空,则用用户自定义的转换器,否则用默认的转换器
TypeConverterconverter=(customConverter!=null?customConverter:bw);
//创建一个BeanDefinitionValueResolver对象
BeanDefinitionValueResolvervalueResolver=
newBeanDefinitionValueResolver(this.beanFactory,beanName,mbd,converter);
//获取构造器的参数个数
intminNrOfArgs=cargs.getArgumentCount();
//循环遍历带index的参数值
//构造器有两种:
//1.带index的,比如:<constructor-orgindex="0"value="123">
//2.不带index的,比如:<constructor-orgname="test"value="123">
for(Map.Entry<Integer,ConstructorArgumentValues.ValueHolder>entry:cargs.getIndexedArgumentValues().entrySet()){
//获取index,其实就是数组的下标,从0开始的。
intindex=entry.getKey();
//如果index值小于0,则抛异常
if(index<0){
thrownewBeanCreationException(mbd.getResourceDescription(),beanName,
"Invalidconstructorargumentindex:"+index);
}
//如果index+1大于参数个数,则参数个数等于index+1
if(index+1>minNrOfArgs){
//由于index是从0开始的,所以参数个数不能直接等于index,必要还要加1
minNrOfArgs=index+1;
}
//获取参数的值
ConstructorArgumentValues.ValueHoldervalueHolder=entry.getValue();
//如果值已经转换过了
if(valueHolder.isConverted()){
//将值对象添加到resolvedValues集合中
resolvedValues.addIndexedArgumentValue(index,valueHolder);
}
else{
//如果值没有转换过,则需要先转换
ObjectresolvedValue=
valueResolver.resolveValueIfNecessary("constructorargument",valueHolder.getValue());
//创建一个值对象
ConstructorArgumentValues.ValueHolderresolvedValueHolder=
newConstructorArgumentValues.ValueHolder(resolvedValue,valueHolder.getType(),valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
//将值对象添加到resolvedValues集合中
resolvedValues.addIndexedArgumentValue(index,resolvedValueHolder);
}
}
//循环遍历不带index的参数值,即普通的参数值
for(ConstructorArgumentValues.ValueHoldervalueHolder:cargs.getGenericArgumentValues()){
//如果值已经转换过了
if(valueHolder.isConverted()){
//将值对象添加到resolvedValues集合中
resolvedValues.addGenericArgumentValue(valueHolder);
}
else{
//如果值没有转换过,则需要先转换
ObjectresolvedValue=
valueResolver.resolveValueIfNecessary("constructorargument",valueHolder.getValue());
//创建一个值对象
ConstructorArgumentValues.ValueHolderresolvedValueHolder=newConstructorArgumentValues.ValueHolder(
resolvedValue,valueHolder.getType(),valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
//将值对象添加到resolvedValues集合中
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
//最后返回参数个数
returnminNrOfArgs;
}这个方法的代码,看起来有点多,但是逻辑还是比较清晰的。
下面用一张图总结一下,这个方法的主要流程:
4 storeCache方法
前面说到的缓存,是通过ArgumentsHolder类的storeCache方法保存进去的,它是ConstructorResolver类的内部类。
并且访问权限是private的,说明ArgumentsHolder类只能在ConstructorResolver类中使用。
ArgumentsHolder类的作用是保存一些参数。
重点看看它的storeCache方法:
将找到的构造器constructorOrFactoryMethod,以及ArgumentsHolder类中的arguments和preparedArguments,设置到RootBeanDefinition中,即设置缓存。
5 instantiate方法
上面多次调用了instantiate方法创建bean实例,我们一起看看这个方法做了些什么事情:
其实就是获取了InstantiationStrategy接口实现类的对象,然后调用该对象的instantiate方法。
如果该BeanDefintion的方法重载属性为false,则直接通过BeanUtils的instantiateClass方法创建bean实例。
否则通过instantiateWithMethodInjection方法,我们主要看CglibSubclassingInstantiationStrategy类的instantiateWithMethodInjection方法:
主要看instantiate方法:
如果构造器为空,则用BeanUtils类的instantiateClass方法,用子类的创建bean实例。
如果构造器不为空,则使用Cglib创建bean实例。
5 策略模式
不知道你们在阅读上面这部分源码的过程中,发现了没,Spring为了将代码更优雅,使用了一些设计模式。
我们一起回头再看看ConstructorResolver类的instantiate的方法。
先通过beanFactory获取InstantiationStrategy接口,实际上会调用它的实现类的instantiate方法。 定义了一个接口:
定义了实现类有两种:Cglib或者JDK动态代理。
这里是策略模式的用法,但跟传统的策略模式稍微有点区别,在这里是将策略模式和工厂模式二者相结合,增加了更多的灵活性。
例如:
publicinterfaceA{
publicvoidtest();
}
publiconeAimplementsA{
@Override
publicvoidtest(){
System.out.println("oneA");
}
}
publictwoAimplementsA{
@Override
publicvoidtest(){
System.out.println("twoA");
}
}
publicclassAContext{
privateAa;
publicAContext(Aa){
this.a=a;
}
publicvoidtest(){
a.test():
}
}策略模式三个要素:
- 定义一个接口。
- 定义接口实现类。
- 定义一个Context类,负责真正的方法调用。
很显然,Spring在这里没有定义Context类。
而是直接使用了AbstractAutowireCapableBeanFactory类
instantiationStrategy是它的成员变量。
它内部仅仅提供了instantiationStrategy的setter和getter方法。
而AbstractAutowireCapableBeanFactory类中的instantiationStrategy不出意外的话,是可以配置的。
可以通过org.graalvm.nativeimage.imagecode参数控制实例化方式。