Spring中bean虽然可以通过多种方式(Supplier接口、FactoryMethod、构造器)创建bean的实例对象,但是使用最多的还是通过构造器创建对象实例,也是我们最熟悉的创建对象的方式。如果有多个构造器时,那Spring是如何推断使用哪个构造器来创建bean对象实例的?
一、Spring中创建对象实例的方式
(1) 通过构造器实例化对象
这是我们创建实例最常使用的方式,也是最常见的方式。
public class ObjectInstance {
private String createMode;
public ObjectInstance(String createMode) {
System.out.println("create by constructor");
this.createMode = createMode;
}
public ObjectInstance() {
}
public String getCreateMode() {
return createMode;
}
public void setCreateMode(String createMode) {
this.createMode = createMode;
}
@Override
public String toString() {
return "ObjectInstance{" +
"createMode='" + createMode + '\'' +
'}';
}
}
<!--通过构造器实例化bean-->
<bean id="objBean" class="cn.crazy.newInstance.ObjectInstance">
<constructor-arg name="createMode" value="create by constructor"></constructor-arg>
</bean>
(2)通过工厂方法实例化对象
public class CrazyInstanceFactory {
//静态工厂方法
public static Object newInstanceForStatic(){
ObjectInstance objectInstance = new ObjectInstance();
objectInstance.setCreateMode("create by factory's static method");
return objectInstance;
}
//实例工厂方法
public Object newInstance(){
ObjectInstance objectInstance = new ObjectInstance();
objectInstance.setCreateMode("create by factory's instance method");
return objectInstance;
}
}
(i)静态工厂方法
<!--通过静态工厂实例化bean-->
<bean id="objInstanceForStaticFactory" class="cn.crazy.newInstance.CrazyInstanceFactory" factory-method="newInstanceForStatic"></bean>
(ii)实例工厂方法
<!--通过实例工厂实例化bean-->
<bean id="crazyInstanceFactory" class="cn.crazy.newInstance.CrazyInstanceFactory"></bean>
<bean id="objInstance" factory-bean="crazyInstanceFactory" factory-method="newInstance"></bean>
(3)通过实现FactoryBean接口实例化对象
public class CrazyFactoryBean implements FactoryBean<ObjectInstance> {
@Override
public ObjectInstance getObject() throws Exception {
ObjectInstance objectInstance = new ObjectInstance();
objectInstance.setCreateMode("create by FactoryBean");
return objectInstance;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return true;
}
}
<!--通过FactoryBean接口实例化bean-->
<bean id="objInstanceForFactoryBean" class="cn.crazy.newInstance.CrazyFactoryBean"></bean>
(4)通过Supplier实例化对象
public class SupplierObj{
private String version;
private int num;
public SupplierObj() {
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public String toString() {
return "SupplierObj{" +
"version='" + version + '\'' +
", num=" + num +
'}';
}
}
使用BeanFactoryPostProcessor对beanDefinition信息进行修改,为其通过一个Supplier,用于实例化bean。
Supplier接口只有一个方法,我们可以用简化语法创建匿名接口实现类。
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
public class MyPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition beanDefinition = (GenericBeanDefinition)beanFactory.getBeanDefinition("supplierObj");
//beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue();
beanDefinition.setInstanceSupplier(() -> {
SupplierObj supplierObj1 = new SupplierObj();
return supplierObj1;
});
}
}
<!--只是设置属性值,并没有进行实例化,但是会把属性信息保存在bd中-->
<bean id="supplierObj" class="cn.crazy.newInstance.SupplierObj">
<property name="num" value="12"></property>
<property name="version" value="1.0.0"></property>
</bean>
二、推断构造器
(1)doCreateBean(),创建bean实例对象。
doCreateBean()方法是Spring进行Bean创建的核心方法,它包含三个参数:
- String beanName,就是bean的id或anme;
- RootBeanDefinition mbd,Spring Bean在没有被创建之前,bean的信息(xml配置bean及注解注入的信息)会被解析成BeanDefinition对象,我们知道Class是描述Java对象信息的,那么BeanDefinition就是描述Spring Bean信息的;
- Object[] args,构造器参数。这个值默认为null,除非程序员自己调用api传入参数。
这个方法中会调用多次后置处理器,用于推断构造器、完成BD合并、解决循环依赖、解析依赖注入注解、完成AOP等。今天主要看推断构造器完成对象实例部分的代码,所以进行了省略。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//第二次调用后置处理器的入口方法(推断构造方法)
//代码块一:创建实例bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
……
//填充属性
//调用第五次和第六次后置处理器的地方
populateBean(beanName, mbd, instanceWrapper);
return exposedObject;
}
(2) createBeanInstance(),根据特定的bean及实例化策略创建一个bean实例。
这个方法大致总结为 :
1)解析beanCless,确保beanClass在此时实际上已被解析。如果BD的beanClass为null,将BD的beanClassName解析成Class,并设置为BD的beanClass值。
2)如果BD中设置了Supplier接口,直接通过这个Supplier实例化bean。
3)如果有工厂方法,使用工厂方法实例化bean。实例化对象的工厂方法也存在重载的情况,推断工厂方法的逻辑与推断构造器的逻辑类似。
4)从缓存中获取对象实例化的方式,不为null的话,说明之前已经完成解析,设置resolved = true(创建对象的构造器已经被解析过)。如果对象的构造器已经被解析过,且构造器参数也完成解析,直接使用之前缓存中的构造器和构造参数完成对象的实例化
5)推断构造方法。先通过较粗略的方式推断出理想的构造器,可能推断出只有一个(仅有一个有参构造器或者仅有一个加了@Autowired且required = true注解的构造器)或多个(存在多个构造器有@Autowired中required = false,且不存在required = true的构造器),甚至为null(只有无参构造器,或存在多个构造器且这些构造没有加@Autowired注解)
6)结合推断出来的构造器和主动装配方法(构造器注入),确定真正用来实例化对象的构造器,解析对应构造器的参数值,完成对象实例化。
为什么要缓存对象的构造器信息?
方便Spring快速的创建对象 ,因为创建对象时,推断构造方法是个很复杂的过程,在创建原型bean时,可以只推断一次,后续不用在执行这个复杂的操作 。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 确保beanClass在此时实际上已被解析
// 将beanName解析为类引用,并把解析后的Class设置到mbd的beanClass属性中
// 代码块一:解析beanClass
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//判断beanClass是否不符合要求
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//这段代码的含义是?spring提供了一个Supplier接口,用于实例化bean
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
// 代码块二:从给定的supplier获取bean实例
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
// 代码块三 : 使用FactoryMethod实例化bean
// 实例化对象的工厂方法也存在重载的情况,推断工厂方法的逻辑与推断构造器的逻辑类似
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
//resolved表示创建对象的构造方法有没有被解析过
/**
* 为什么要有这个标签?
* 方便spring快速的创建对象
* 因为创建对象时,推断构造方法是个很复杂的过程,在创建原型bean时,可以只推断一次,后续不用在执行这个复杂的操作
*/
boolean resolved = false;
//构造函数参数是否被解析过
boolean autowireNecessary = false;
//args是goGetBean(……,args,……)的入参,spring自身传入为null
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
//表示已经找到了创建对象的方式
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//单例情况下不会执行这个判断,原型时会用到
if (resolved) {
if (autowireNecessary) {
// 为什么这个方法的后两个参数(ctors和explictArgs)为null?因为这两个值可以从缓存中获取
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用无参构造器实例化bean
return instantiateBean(beanName, mbd);
}
}
//推断构造方法,有多个构造方法是,推断出最合适的,如果只有一个构造方法,返回null(不用推断)
// Candidate constructors for autowiring?
//第二次调用后置处理器
//代码块四:推断构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
//如果自动注入的方式为构造器注入,会再一次推断构造方法
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//代码五:确定构造方法参数的值
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
(3)代码块一:resolveBeanClass(),确保beanClass在此时实际上已被解析。
这个方法就是将beanName解析为类引用,并把解析后的Class设置到mbd的beanClass属性中。
@Nullable
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
//解析beanClass
return doResolveBeanClass(mbd, typesToMatch);
}
}
……
}
@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throws ClassNotFoundException {
//获取bean对应的类加载器
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader dynamicLoader = beanClassLoader;
boolean freshResolve = false;
if (!ObjectUtils.isEmpty(typesToMatch)) {
// When just doing type checks (i.e. not creating an actual instance yet),
// use the specified temporary class loader (e.g. in a weaving scenario).
//当只是进行类型检查时(即还没有创建实际的实例),使用指定的临时类加载器(例如在编织场景中)。
ClassLoader tempClassLoader = getTempClassLoader();
if (tempClassLoader != null) {
dynamicLoader = tempClassLoader;
freshResolve = true;
if (tempClassLoader instanceof DecoratingClassLoader) {
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
for (Class<?> typeToMatch : typesToMatch) {
dcl.excludeClass(typeToMatch.getName());
}
}
}
}
String className = mbd.getBeanClassName();
if (className != null) {
// className不为null时,解析出className的实际值
// className可能是个表达式或有特殊字符,通过evaluateBeanDefinitionString()计算出结果
Object evaluated = evaluateBeanDefinitionString(className, mbd);
if (!className.equals(evaluated)) {
// A dynamically resolved expression, supported as of 4.2...
if (evaluated instanceof Class) {
return (Class<?>) evaluated;
}
//如果是String类型,通过类加载器加载对应的class
else if (evaluated instanceof String) {
className = (String) evaluated;
freshResolve = true;
}
else {
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
}
}
if (freshResolve) {
// When resolving against a temporary class loader, exit early in order
// to avoid storing the resolved Class in the bean definition.
if (dynamicLoader != null) {
try {
return dynamicLoader.loadClass(className);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
}
}
}
//反射调用,根据className返回不同类型的Class
return ClassUtils.forName(className, dynamicLoader);
}
}
// 定期解析,在BeanDefinition中缓存结果
// Resolve regularly, caching the result in the BeanDefinition...
return mbd.resolveBeanClass(beanClassLoader);
}
@Nullable
public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
String className = getBeanClassName();
if (className == null) {
return null;
}
// 将解析出来的Class存储到BD的beanClass中
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
}
(4) 代码块二:obtainFromSupplier(),从给定的supplier获取bean实例。
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
// 通过instanceSupplier.get()获取bean实例
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
if (instance == null) {
instance = new NullBean();
}
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
(5) 代码块三 : instantiateUsingFactoryMethod(),使用FactoryMethod实例化bean。
实例化对象的工厂方法也存在重载的情况,推断工厂方法的逻辑与推断构造器的逻辑类似。就不过多阐述,后续看推断构造器的代码。
//通过FactoryMethod实例化对象
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;
String factoryBeanName = mbd.getFactoryBeanName();
//设置了factoryBean,说明是实例工厂方法
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 根据factoryBeanName获取对应的factoryBean,通过factoryBean创建实例
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// 静态工厂方法
// It's a static factory method on the bean class.
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}
// ……省略获取缓存的代码
if (factoryMethodToUse == null || argsToUse == null) {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
factoryClass = ClassUtils.getUserClass(factoryClass);
List<Method> candidates = null;
if (mbd.isFactoryMethodUnique) {
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) {
candidates = new ArrayList<>();
//获取factoryClass所有的method
// ReflectionUtils.getAllDeclaredMethods(factoryClass)
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
for (Method candidate : rawCandidates) {
// 如果是静态方法且与mbd.getFactoryMethodName()一致,加入候选列表中
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}
//……后续处理逻辑基本与推断构造器类似
}
(6)代码块四:determineCandidateConstructors(),推断构造器
推断构造器是通过一个后置处理器AutowiredAnnotationBeanPostProcessor来完成的,这个后置处理器是Spring启动时自动添加的。
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// 省略lookup methods检查
//先从缓存中拿,拿不到再进行推断
// Quick check on the concurrent map first, with minimal locking.
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 {
//getDeclared拿到所有类型的(public、protected、private),但不会拿父类的
//拿到所有的构造器
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;
//没有使用到kotlin时永远返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
for (Constructor<?> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
//beanClass是个CGLIB代理类,找到父类
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
if (ann != null) {
//已经有@Autowired(required=true)标记的构造器时,如果再出现@Autowired标记的构造器时会抛出异常
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或@Value注解
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
//@Autowired(required=true)的构造器才会设置为requiredConstructor
requiredConstructor = candidate;
}
//只有添加了构造方法上加了@Autowired或@Value注解,该构造方法都会放入candidates
candidates.add(candidate);
}
else if (candidate.getParameterCount() == 0) {
//defaultConstructor设置为无参构造器
defaultConstructor = candidate;
}
}
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null) {
if (defaultConstructor != null) {
//如果candidates不能空,且无确定的构造方法,添加默认的构造方法到可选列表中
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
//将candidates转换为构造器数组
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//仅当一个有参构造方法时,才会返回这个构造方法
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
// primaryConstructor永远为null
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
//空构造器数组
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
这个方法大致总结为:
1)先从缓存中获取候选构造器数组, 如果能获取成功,判断数组长度是否大于0,大于0则返回这个构造器数组,否则返回null。不存在缓存则进行步骤2。
2)获取beanClass中的所有类型的构造器(public、protected、private),存放到rawCandidates数组。创建一个存放候选构造器的List集合candidates,长度为 rawCandidates数组的长度,创建三个构造器类型的变量requiredConstructor(存储@Autowired(required = true)标记的构造器)、defaultConstructor(存储默认的构造器)和primaryConstructor(没有使用到kotlin时永远返回null
),创建一个int类型的变量nonSyntheticConstructors,用于记录beanClass非合成构造器的个数。
3)遍历rawCandidates数组,如果当前的构造器对象为非合成构造器nonSyntheticConstructors计数器+1。定义一个MergedAnnotation类型变量ann,存放当前构造器的Autowired注解信息,如果当前beanClass的ann为null,判断beanClass是否为CGLIB代理类,如果是,将父类相同(参数类型相同)构造器上的Autowired注解信息赋值给ann。
(a)如果注解信息ann不为null
(i)判断requiredConstructor是否为null,如果不为null,说明beanClass中已经存在一个@Autowired(required=true)的构造器,抛出异常!
(ii)获取当前构造器上的注解信息ann的required属性值,如果为true,如果候选构造器的List集合candidates不为空,抛出异常。否则将当前构造器赋值给requiredConstructor变量。
(iii)将当前构造器加入到候选构造器的List集合candidates中。
(b) 如果注解信息ann为null
如果当前构造器为无参构造器,将当前构造器赋值给defaultConstructor变量。
4)完成遍历后,有如下几种情况
(a)candidates不为空的情况,如果requiredConstructor为null,defaultConstructor不为null,将defaultConstructor加入候选构造器集合candidates中。将candidates转换为构造器数组对象。【返回一个或多个】
(b)rawCandidates数组长度为1且其中的构造器参数个数大于0(仅当一个有参构造方法时,才会返回这个构造方法),将这个构造器对象封装成构造器数组对象。【返回一个】
(c)nonSyntheticConstructors==2(beanClass只有两个非合成构造器)且primaryConstructor不为null(没有使用到kotlin时永远返回null),将primaryConstructor和defaultConstructor封装成构造器数组对象。【排除】
(d)nonSyntheticConstructors==1且primaryConstructor不为null(没有使用到kotlin时永远返回null),将primaryConstructorr封装成构造器数组对象。【排除】
(e)不是以上情况,返回空构造器数组对象。【返回空数组,长度为0】
5)将构造器数组对象缓存到spring容器中,并返回这个数组对象。
(7)代码块五:autowireConstructor(),确定构造器及构造器方法参数的值,完成对象实例化。
通过推断构造器方法只是推断出合适的构造器,但是可能存在多个候选构造器的情况,而且构造器的参数值也还没有确定,接下来就是确定构造方法参数的值,并完成对象的实例化。
{
……
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
//如果自动注入的方式为构造器注入,会再一次推断构造方法
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//确定构造方法参数的值
return autowireConstructor(beanName, mbd, ctors, args);
}
……
}
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
//这里只是简单初始化
public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
this.logger = beanFactory.getLogger();
}
这里定义了很多中间变量,如:
//最终使用的构造方法 Constructor<?> constructorToUse = null; //最终使用的参数持有者,维护了参数差异值比较的方法 ArgumentsHolder argsHolderToUse = null; //最终使用的构造方法参数 Object[] argsToUse = null; //这个值默认为null,除非程序员自己调用api传入参数 //createBean(beanName, mbd, args);中args即是explicitArgs Object[] explicitArgs; //解析出来的构造器参数值 //解析出来的参数不一定就是可以直接注入的属性,需要进行转换 //如<constructor-arg type="" ></constructor-arg>或如<constructor-arg ref="" ></constructor-arg> //需要转换成具体的Bean才能注入 Object[] argsToResolve = null; //最小参数个数,如果手动设置构造器参数,createBean(beanName, mbd, args)或 //xml配置了<constructor-arg></constructor-arg> //或设置了BeanDefinition.getConstructorArgumentValues().addArgumentValues(); //最小参数个数就是设置参数的个数 int minNrOfArgs;
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
//最终使用的构造方法
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
//最终使用的构造方法参数
Object[] argsToUse = null;
//构造器参数。这个值默认为null,除非程序员自己调用api传入参数
//createBean(beanName, mbd, args);中args即是explicitArgs
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
//解析出来的构造参数
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
//尝试从缓存中获取
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
//从缓存中获取构造参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
//构造器中没有缓存构造参数,就需要获取preparedConstructorArguments
//部分准备好的构造函数参数,不是最终使用的构造器参数,需要转换
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
//解析出来的参数不一定就是可以直接注入的属性,需要进行转换
//如<constructor-arg type="" ></constructor-arg>或如<constructor-arg ref="" ></constructor-arg>
//需要转换成具体的Bean才能注入
// 代码块六:进行构造器参数的转换
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
//拿出所有的构造方法
// mbd.isNonPublicAccessAllowed() == true,是否允许非public修饰的构造器
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + 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;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
//通过无参构造器实例化bean
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// Need to resolve the constructor.
//如果构造器不为空或者配置了自动装配方式为构造器注入则需要自动装配
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
//最小参数个数
int minNrOfArgs;
//实际传入构造方法参数个数不为null
if (explicitArgs != null) {
//如果指定了构造器参数值,最小参数个数为指定的参数个数
minNrOfArgs = explicitArgs.length;
}
else {
//xml配置了<constructor-arg></constructor-arg>
//或设置了BeanDefinition.getConstructorArgumentValues().addArgumentValues();
//就根据手动设置的构造器参数推断出所需要的构造器
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
//代码块七:计算出构造器的最小参数个数,并根据手动设置的构造参数值构建ConstructorArgumentValues对象
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//代码块八:对candidates进行排序
AutowireUtils.sortConstructors(candidates);
//计算权重
int minTypeDiffWeight = Integer.MAX_VALUE;
//存放摸棱两可的构造器
Set<Constructor<?>> ambiguousConstructors = null;
Deque<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
int parameterCount = candidate.getParameterCount();
//因为进行了排序,如果当前的parameterCount<argsToUse.length,那么后续candidate.parameterCount总是小于argsToUse.length
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//当前构造方法参数个数不满足要求,跳过本次循环
if (parameterCount < minNrOfArgs) {
continue;
}
// 参数持有者
ArgumentsHolder argsHolder;
//构造器参数类型数组
Class<?>[] paramTypes = candidate.getParameterTypes();
if (resolvedValues != null) {
try {
//得到当前构造器的方法参数名字数组
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
//代码块九:根据构造方法参数名数组和构造器参数值构建argsHolder
//这个方法就是遍历构造器的参数名字和参数类型,找到与之匹配的resolvedValues中的ValueHolder值,并封装成ArgumentsHolder对象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
if (parameterCount != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
//计算差异值,当多个构造方法的参数个数相同时,通过差异值决定使用哪个构造方法
//mbd.isLenientConstructorResolution()是否为宽松模式,默认是宽松模式
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
//如果当前构造器的差异值比minTypeDiffWeight小,将当前构造器的差异值赋值给minTypeDiffWeight变量
if (typeDiffWeight < minTypeDiffWeight) {
//最终使用的构造器constructorToUse赋值为当前构造器
constructorToUse = candidate;
//最终使用的参数持有者argsHolderToUse赋值为当前的argsHolder
argsHolderToUse = argsHolder;
//最终使用的构造器参数argsToUse赋值为当前的argsHolder的arguments
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
// 如果两个构造器的差异值相等,就会将它放入ambiguousConstructors中
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//如果存在模棱两可的构造器且不是宽松模式,抛出异常
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
if (explicitArgs == null && argsHolderToUse != null) {
//代码块十:将推断出来的构造方法信息缓存到BD中
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
//代码块十一:根据推断出来的构造器及其参数创建bean实例,并封装到bw对象中
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
这个方法大致总结为:
1)先后bd缓存中获取构造函数的相关信息(构造器、构造参数),如果缓存是部分准备好的构造函数参数,需要转换成最终可使用的构造参数。
2)缓存中获取构造器或构造参数失败,有如下两种情况:
a.通过determineCandidateConstructors()推断出来的构造器不为null,直接将推断出来的构造器存放到构造器数组candidates。
b.通过determineCandidateConstructors()推断出来的构造器为null,拿到当前beanClass中的所有构造器,存放到构造器数组candidates。
3)如果candidates中只有一个构造器且为无参构造,将该构造器信息缓存到bd中,同时通过这个无参构造器创建bean实例对象,并封装到BeanWrapperImpl中返回。
4)设置构造器最小参数值minNrOfArgs。如果手动设置了构造器参数,最小参数值就为设置的参数的个数。(通过createBean(beanName, mbd, args)api设置args或者通过xml中<constructor-arg>标签设置。或者是BeanDefinition.getConstructorArgumentValues().addArgumentValues()/BeanDefinition.getConstructorArgumentValues().addIndexedArgumentValue()方式设置)获取bd中的构造参数值,并封装成ConstructorArgumentValues对象(resolvedValues)。
5)对candidates中的构造器进行排序。创建构造器差异值变量minTypeDiffWeight,并将其赋值为Integer.MAX_VALUE(构造器差异值最小的即为最优解);创建 ambiguousConstructors 变量用于存放模棱两可的构造器。
6)遍历candidates,获取当前构造器的参数个数parameterCount,如果上一个回合已经推断出constructorToUse和argsToUse,且argsToUse的长度大于当前构造器的参数个数,直接退出遍历。(因为进行了排序,如果当前的parameterCount<argsToUse.length,那么后续candidate.parameterCount可能总是小于argsToUse.length,虽然可能存在修饰符不同的情况,但是这里排序修饰符比构造参数个数优先级高)。在遍历的代码块中有一个重要的逻辑就是计算差异值,而计算差异值的前提是两个构造器的构造参数个数相同。如果当前构造器比前一个构造器的构造参数个数少,是没有资格进行差异值比较的。
7)如果当前构造器的个数parameterCount 小于最小构造器参数个数minNrOfArgs,跳过本次循环,进行下次循环(pubulic修饰的构造器参数个数不满足,可能protected或private修饰的构造器参数个数满足条件,因为构造器排序是根据修饰符进行排序,修饰符相同,再根据参数个数进行排序)。需要注意的是,排在前面的构造器参数个数不一定多余排在后面的构造器参数个数,所以这里是continue,而不是break。步骤6和这里也不冲突,只有参数个数满足条件的前提下才能成为被使用的constructorToUse。
8)构建参数持有者ArgumentsHolder argsHolder,获取当前构造器的构造器参数类型数组Class<?>[] paramTypes。
(i)resolvedValues值不为空。获取当前构造器参数名字数组。遍历构造器的参数名字和参数类型数组,找到与之匹配的resolvedValues中的ValueHolder值,并封装成ArgumentsHolder对象。
(ii)explicitArgs不为空,直接通过explicitArgs构建ArgumentsHolder对象。
9)计算差异值,当多个构造器的参数个数相同时,通过差异值决定使用哪个构造器。
(i)如果当前构造器的差异值比minTypeDiffWeight小,将当前构造器的差异值赋值给minTypeDiffWeight变量,并把最终使用的构造器constructorToUse赋值为当前构造器 constructorToUse = candidate; 最终使用的参数持有者argsHolderToUse赋值为当前的argsHolder argsHolderToUse = argsHolder; 最终使用的构造器参数argsToUse赋值为当前的argsHolder的arguments。同时将ambiguousConstructors值设置为null.
(ii) 如果当前构造器的差异值与minTypeDiffWeig相等,就会将它放入ambiguousConstructors(如果为null,先创建ambiguousConstructors)中。
10)如果存在模棱两可的构造器(ambiguousConstructors有值)且不是宽松模式下,抛出异常。严格模式下,Spring认为不能存在摸棱两可的构造器,而且宽松模式和严格模式下差异值计算的算法也不一样。Spring默认为宽松模式。
11)将推断出来的构造方法信息缓存到BD中,并根据推断出来的构造器及其参数创建bean实例,并封装到bw对象中返回。
(i)代码块八:sortConstructors(),对候选构造器集合进行排序
构造器的排序规则。public修饰的构造器排在前面,如果同为public类型,比较构造器的参数个数,参数个数多的排在前面。
public static void sortConstructors(Constructor<?>[] constructors) {
Arrays.sort(constructors, EXECUTABLE_COMPARATOR);
}
public static final Comparator<Executable> EXECUTABLE_COMPARATOR = (e1, e2) -> {
int result = Boolean.compare(Modifier.isPublic(e2.getModifiers()), Modifier.isPublic(e1.getModifiers()));
//为什么在自动注入方式为构造方法注入时,会选择构造方法参数比较多的那个构造方法
return result != 0 ? result : Integer.compare(e2.getParameterCount(), e1.getParameterCount());
};
(ii)代码块十:storeCache(),将推断出来的构造方法信息缓存到BD中
//将推断出来的构造方法信息缓存到BD中
public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
mbd.constructorArgumentsResolved = true;
if (this.resolveNecessary) {
mbd.preparedConstructorArguments = this.preparedArguments;
}
else {
mbd.resolvedConstructorArguments = this.arguments;
}
}
}
}
(8)代码块六:resolvePreparedArguments(),进行构造器参数的转换。
解析出来的参数不一定就是可以直接注入的属性,需要转换成具体的Bean才能注入。如<constructor-arg type="" ></constructor-arg>或如<constructor-arg ref="" ></constructor-arg>。
这里分支很多,我们看看使用了ref标签值得处理,Spring很多地方都会对String字符串进行运行解析,可能这些字符串是一个需要解析的表达式或有其他含有的字段,通过运行得到最终的结果。
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
Executable executable, Object[] argsToResolve, boolean fallback) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
Class<?>[] paramTypes = executable.getParameterTypes();
Object[] resolvedArgs = new Object[argsToResolve.length];
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
Object argValue = argsToResolve[argIndex];
MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
if (argValue == autowiredArgumentMarker) {
argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback);
}
else if (argValue instanceof BeanMetadataElement) {
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
}
else if (argValue instanceof String) {
argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
}
Class<?> paramType = paramTypes[argIndex];
try {
resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
}
return resolvedArgs;
}
// 给定PropertyValue,返回一个值,解析对其他属性的任何引用
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
// 如果value是引用类型,如使用了ref指向的bean的id或name,需要找到对应的beanClass
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
// 解析对工厂中另一个bean的引用
return resolveReference(argName, ref);
}
……
}
/**
* 解析对工厂中另一个bean的引用。
* Resolve a reference to another bean in the factory.
*/
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
// 这是为null,暂时没有找到设置值的地方<constructor-arg name="refName" type="xxx">设置不生效
Class<?> beanType = ref.getBeanType();
// 是否是对父工厂中的bean的显式引用
if (ref.isToParent()) {
BeanFactory parent = this.beanFactory.getParentBeanFactory();
if (parent == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean " + ref +
" in parent factory: no parent factory available");
}
if (beanType != null) {
bean = parent.getBean(beanType);
}
else {
bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
}
}
else {
String resolvedName;
if (beanType != null) {
//根据requiredType获取对应的beanNme(如果在allBeanNamesByType或singletonBeanNamesByType中没找到,到beanDefinitionNames找)
//找到对应的beanName,再根据这个beanName和type到容器中getBean,最后构建NamedBeanHolder
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
bean = namedBean.getBeanInstance();
resolvedName = namedBean.getBeanName();
}
else {
// ref标签设置了bean属性值<ref bean="beanName"/>或<constructor-arg name="refName" ref="beanName">
// 对beanName进行运算得到最终的引用对象的name
resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
// 通过name到容器中获取对应的bean
bean = this.beanFactory.getBean(resolvedName);
}
this.beanFactory.registerDependentBean(resolvedName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
(9)代码块七:resolveConstructorArguments(),计算出构造器的最小参数个数,并根据手动设置的构造参数值构建ConstructorArgumentValues对象。
因为index是从0开始的,如果minNrOfArgs < index +1,最小的构造器参数个数为手动设置的构造参数个数。至少保证手动设置的值能被运用到构造器中。这个方法还有一个重要功能就是构造器参数转换,从bd里面获取构造参数,遍历完成每个参数的转换,转换的代码逻辑跟代码六一致。
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
int minNrOfArgs = cargs.getArgumentCount();
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
int index = entry.getKey();
if (index < 0) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid constructor argument index: " + index);
}
if (index + 1 > minNrOfArgs) {
minNrOfArgs = index + 1;
}
// 参数持有者
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
// 是否已经完成转换,
if (valueHolder.isConverted()) {
resolvedValues.addIndexedArgumentValue(index, valueHolder);
}
else {
// 进行类型转换
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
//是否已经转换
if (valueHolder.isConverted()) {
resolvedValues.addGenericArgumentValue(valueHolder);
}
else {
//根据不同的类型,转换成对应类型的值
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
//转换成可以直接注入的值
ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
return minNrOfArgs;
}
(10)代码块九:createArgumentArray(),构建构造器参数数组。
这个方法就是遍历构造器的参数名字和参数类型,找到与之匹配的resolvedValues中(步骤9中构建的ConstructorArgumentValues对象)的ValueHolder值,并封装成ArgumentsHolder对象。
这里的匹配规则代码量太多,后续详细展开说说。
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//根据构造器的参数名和参数类型匹配ConstructorArgumentValues中的valueHolder,并封装到ArgumentsHolder中
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
//先根据paramType获取ArgumentValue,例如Class类型的话,获取不到ArgumentValue
//获取resolvedValues中type和name与构造器中的参数名和参数类型相匹配的ValueHolder
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
//如果是自动注入(配置了自动装配方式为构造器注入)或半自动注入(@Autowire(require=true)标识的唯一构造器)的话,不会从ArgumentValue中获取值
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
//先根据paramType获取不到ArgumentValue,获取模糊的ArgumentValue
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
//已经完成转换,直接从valueHolder中获取转换后的对象
if (valueHolder.isConverted()) {
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
//先用转换器进行类型转换
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
}
args.arguments[paramIndex] = convertedValue;
args.rawArguments[paramIndex] = originalValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
try {
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
三、总结
spring推断构造方法分如下几种情况:
(1)不使用自动装配时。
1)无构造方法或只有一个无参构造方法的情况下,返回null
2)有且只有一个有参构造方法时,返回这个有参构造方法
3)有多个构造方法时,返回null
(2)使用@Autowired注入时.
1)如果只有一个构造方法添加了@Autowired(required=true),返回这个构造方法
2)如果有一个构造方法添加了@Autowired(required=true),其他构造方法再添加@Autowired注解,抛出异常
3)如果有多个构造方法添加了@Autowired(required=false),除了返回所以加了@Autowired(required=false)的构造方法,如果提供了无参构造方法,也会返回无参构造方法,后续继续推断构造方法。
(3)使用自动注入时。
根据构造方法的参数类型或参数个数找到最优的构造方法,默认最优的为参数类型为spring中依赖最多,且参数个数最长的那个。