MyBatis源码学习(二)——创建Mapper代理工厂的准备工作

先上小结:

  1. @Autowired注解生效。
  2. Spring开始为@Autowired注解的Mapper创建动态代理。使用的是BeanFatory中注册的BeanDefinition。
  3. Spring标准的创建动态代理流程,创建Mapper接口类的BeanWrapper,准备进行属性注入。
  4. 准备给Mapper代理注入sqlSessionFactory和sqlSessionTemplate。
  5. Spring标准的创建动态代理流程,创建SqlSessionFactory的代理。使用的是SqlSessionFactory的BeanDefinition。SqlSessionFactory的BeanDefinition是MybatisAutoConfiguration类加载时,被@Bean注解和@ConditionalOnMissingBean注解创建完成的。
  6. 通过SqlSessionFactory的BeanDefinition,可以得知SqlSessionFactory的类名beanName(其值是sqlSessionFactory),所属的工厂factoryBean(其值是MybatisAutoConfiguration实例),创建实例的方法名factoryMethodToUse(其值是sqlSessionFactory方法),构造的参数argsToUse(参数只有一个,是DruidDataSourceWrapper实例),下面就可以创建SqlSessionFactory实例代理了。

 

正文:

在前面的代码流程中,在@MapperScan注解的作用下,各个Mapper接口类都创建了对应的BeanDefinition,并且添加到了Spring的BeanDefinition列表中。

如果我们在Service中使用:

@Autowired
private OrderMapper orderMapper;

这种写法来使用Mapper接口,此时Spring中的BeanDefinition列表还会包含Service的BeanDefinition。

那么,这个时候BeanDefinition列表包含Mapper,Service,MybatisAutoConfiguration,sqlSessionFactory,sqlSessionTemplate等各种类别的BeanDefinition,上面列出来的是和Mybatis有点关系的,另外还有Spring要用到的一大堆东西,都是准备创建动态代理的。

接下来,Spring会为BeanDefinition列表中每一个记录在案的BeanDefinition创建动态代理,对于Mapper的BeanDefinition来说,这里创建的动态代理其实是Mapper的代理工厂,真正Mapper的动态代理是在创建Service动态代理时,依据@Autowired注解,在依赖注入的流程中创建的。

 

Spring为每个BeanDefinition创建动态代理的代码源自DefaultListableBeanFactory的preInstantiateSingletons()方法:

@Override
public void preInstantiateSingletons() throws BeansException {
	if (this.logger.isDebugEnabled()) {
		this.logger.debug("Pre-instantiating singletons in " + this);
	}

	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	List beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					final FactoryBean factory = (FactoryBean) bean;
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged((PrivilegedAction)
										((SmartFactoryBean) factory)::isEagerInit,
								getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
			}
			else {
				getBean(beanName);
			}
		}
	}

	// Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}

可以看到,方法一开始用beanDefinitionNames组装了一个列表beanNames,开始循环并创建代理,而且在处理逻辑中,对于工厂类和非工厂类的BeanDefinition采用了不同的处理逻辑,Mapper接口类在BeanDefinition中定义的代理类是MapperFactoryBean,属于工厂类,注意一下这行代码:

Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);

创建bean的时候在原本的beanName前面加了一个FACTORY_BEAN_PREFIX标识,这是一个工厂类的标识,实际上是一个&字符,所以getBean()方法的参数实际上是 &orderMapper这样的,后面的代码逻辑中,也会用这个工厂类标识符来判断这是不是一个工厂类。

经过了getBean(),doGetBean(),getSingleton()等一系列方法的调用,这些过程省略,代码来到了AbstractAutowireCapableBeanFactory的doCreateBean()方法:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }

    if (instanceWrapper == null) {
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    Object bean = instanceWrapper.getWrappedInstance();
    Class beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    Object var7 = mbd.postProcessingLock;
    synchronized(mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            } catch (Throwable var17) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
            }

            mbd.postProcessed = true;
        }
    }

    boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    if (earlySingletonExposure) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
        }

        this.addSingletonFactory(beanName, () -> {
            return this.getEarlyBeanReference(beanName, mbd, bean);
        });
    }

    Object exposedObject = bean;

    try {
        this.populateBean(beanName, mbd, instanceWrapper);
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
            throw (BeanCreationException)var18;
        }

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = this.getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                String[] dependentBeans = this.getDependentBeans(beanName);
                Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                String[] var12 = dependentBeans;
                int var13 = dependentBeans.length;

                for(int var14 = 0; var14 < var13; ++var14) {
                    String dependentBean = var12[var14];
                    if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }

                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    try {
        this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
        return exposedObject;
    } catch (BeanDefinitionValidationException var16) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
    }
}

方法首先调用this.createBeanInstance()方法创建了Mapper接口类的BeanWrapper,BeanWrapper中封装了Mapper接口类的实例代理,实际上是一个MapperFactoryBean类的实例,然后对BeanWrapper进行了组装,需要关注的是其中这两行:

this.populateBean(beanName, mbd, instanceWrapper);

和他的下一行:

exposedObject = this.initializeBean(beanName, exposedObject, mbd);

其中this.populateBean()方法是对Mapper实例进行属性注入,本文下面的部分主要讲解这个方法。

至于exposedObject = this.initializeBean()这个方法是创建Mapper代理工厂的方法,将在后面的文章中专门分析。

下面看一下this.populateBean()的代码:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
    } else {
        boolean continueWithPropertyPopulation = true;
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Iterator var5 = this.getBeanPostProcessors().iterator();

            while(var5.hasNext()) {
                BeanPostProcessor bp = (BeanPostProcessor)var5.next();
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (continueWithPropertyPopulation) {
            PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
            if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                if (mbd.getResolvedAutowireMode() == 1) {
                    this.autowireByName(beanName, mbd, bw, newPvs);
                }

                if (mbd.getResolvedAutowireMode() == 2) {
                    this.autowireByType(beanName, mbd, bw, newPvs);
                }

                pvs = newPvs;
            }

            boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
            boolean needsDepCheck = mbd.getDependencyCheck() != 0;
            PropertyDescriptor[] filteredPds = null;
            if (hasInstAwareBpps) {
                if (pvs == null) {
                    pvs = mbd.getPropertyValues();
                }

                Iterator var9 = this.getBeanPostProcessors().iterator();

                while(var9.hasNext()) {
                    BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                        PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            if (filteredPds == null) {
                                filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                            }

                            pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                            if (pvsToUse == null) {
                                return;
                            }
                        }

                        pvs = pvsToUse;
                    }
                }
            }

            if (needsDepCheck) {
                if (filteredPds == null) {
                    filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }

                this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
            }

            if (pvs != null) {
                this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
            }

        }
    }
}

因为之前创建BeanDefinition的时候把resolvedAutowireMode设置成了2,所以Bean会按类型进行注入,调用以下代码:

this.autowireByType(beanName, mbd, bw, newPvs);

autowireByType()方法的代码:

protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    TypeConverter converter = this.getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    Set autowiredBeanNames = new LinkedHashSet(4);
    String[] propertyNames = this.unsatisfiedNonSimpleProperties(mbd, bw);
    String[] var8 = propertyNames;
    int var9 = propertyNames.length;

    for(int var10 = 0; var10 < var9; ++var10) {
        String propertyName = var8[var10];

        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            if (Object.class != pd.getPropertyType()) {
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
                DependencyDescriptor desc = new AbstractAutowireCapableBeanFactory.AutowireByTypeDependencyDescriptor(methodParam, eager);
                Object autowiredArgument = this.resolveDependency(desc, beanName, autowiredBeanNames, (TypeConverter)converter);
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }

                Iterator var17 = autowiredBeanNames.iterator();

                while(var17.hasNext()) {
                    String autowiredBeanName = (String)var17.next();
                    this.registerDependentBean(autowiredBeanName, beanName);
                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }

                autowiredBeanNames.clear();
            }
        } catch (BeansException var19) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, var19);
        }
    }

}

我们看到方法开始调用了:

String[] propertyNames = this.unsatisfiedNonSimpleProperties(mbd, bw);

这段代码是从BeanWrapper中得到非简单属性的属性名,非简单属性不能是数字,字符串等类型,而且需要有set方法。

BeanWrapper的属性保存在BeanWrapper的propertyDescriptorCache中,维护了一个Map,key是属性名,value是PropertyDescriptor,一共有9个,分别是:

addToConfig,class,mapperInterface,object,objectType,singleton,sqlSession,sqlSessionFactory,sqlSessionTemplate

上面的方法要获得的是非简单属性的属性名,只有sqlSessionFactory,sqlSessionTemplate这两个符合条件,获得这两个属性名是要创建这两个非简单属性的代理。

 

下面的代码,就是分别创建sqlSessionFactory和sqlSessionTemplate的代理。

得到sqlSessionFactory和sqlSessionTemplate这两个名字后,首先根据属性名字从BeanWrapper里获得PropertyDescriptor:

PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);

刚才获得属性名的时候就把PropertyDescriptor循环了一遍,为什么当时不直接取出来……

后面是从PropertyDescriptor中获取set方法:

MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);

MethodParameter是Method的一个封装,此时封装的方法就是setSqlSessionFactory()方法,并且记录了方法的参数:org.apache.ibatis.session.SqlSessionFactory,记录方法返回值:void。

后面的代码:

boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());

代表是否饥饿。

然后调用以下方法:

DependencyDescriptor desc = new AbstractAutowireCapableBeanFactory.AutowireByTypeDependencyDescriptor(methodParam, eager);

拼装了一个DependencyDescriptor,这是一个用于注入的依赖,后面将用此参数完成依赖注入。

下面,就是调用:

Object autowiredArgument = this.resolveDependency(desc, beanName, autowiredBeanNames, (TypeConverter)converter);

此方法就是创建sqlSessionFactory代理,并把此代理注入到Mapper实例的方法,看一下其代码:

@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    descriptor.initParameterNameDiscovery(this.getParameterNameDiscoverer());
    if (Optional.class == descriptor.getDependencyType()) {
        return this.createOptionalDependency(descriptor, requestingBeanName);
    } else if (ObjectFactory.class != descriptor.getDependencyType() && ObjectProvider.class != descriptor.getDependencyType()) {
        if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            return (new DefaultListableBeanFactory.Jsr330Factory()).createDependencyProvider(descriptor, requestingBeanName);
        } else {
            Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
            if (result == null) {
                result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }

            return result;
        }
    } else {
        return new DefaultListableBeanFactory.DependencyObjectProvider(descriptor, requestingBeanName);
    }
}

方法里面有这么一行:

Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);

这个代表是否延迟初始化,可以用@Lazy注解标识延迟初始化,不过Mybatis的Mapper接口代理貌似用不上这个,返回的是null,会调用后面的这行代码:

result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

这里的requestingBeanName就是Mapper接口类的名字,autowiredBeanNames就是sqlSessionFactory(实际上是一个单元素HashSet)。

方法代码:在DefaultListablBeanFactory类中

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

    Object var7;
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut == null) {
            Class type = descriptor.getDependencyType();
            Object value = this.getAutowireCandidateResolver().getSuggestedValue(descriptor);
            Object var23;
            if (value != null) {
                if (value instanceof String) {
                    String strVal = this.resolveEmbeddedValue((String)value);
                    BeanDefinition bd = beanName != null && this.containsBean(beanName) ? this.getMergedBeanDefinition(beanName) : null;
                    value = this.evaluateBeanDefinitionString(strVal, bd);
                }

                TypeConverter converter = typeConverter != null ? typeConverter : this.getTypeConverter();

                try {
                    var23 = converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
                    return var23;
                } catch (UnsupportedOperationException var18) {
                    Object var25 = descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter());
                    return var25;
                }
            }

            Object multipleBeans = this.resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
            if (multipleBeans != null) {
                var23 = multipleBeans;
                return var23;
            }

            Map matchingBeans = this.findAutowireCandidates(beanName, type, descriptor);
            String autowiredBeanName;
            if (matchingBeans.isEmpty()) {
                if (this.isRequired(descriptor)) {
                    this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }

                autowiredBeanName = null;
                return autowiredBeanName;
            }

            Object instanceCandidate;
            Object result;
            if (matchingBeans.size() > 1) {
                autowiredBeanName = this.determineAutowireCandidate(matchingBeans, descriptor);
                if (autowiredBeanName == null) {
                    if (!this.isRequired(descriptor) && this.indicatesMultipleBeans(type)) {
                        result = null;
                        return result;
                    }

                    result = descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                    return result;
                }

                instanceCandidate = matchingBeans.get(autowiredBeanName);
            } else {
                Entry entry = (Entry)matchingBeans.entrySet().iterator().next();
                autowiredBeanName = (String)entry.getKey();
                instanceCandidate = entry.getValue();
            }

            if (autowiredBeanNames != null) {
                autowiredBeanNames.add(autowiredBeanName);
            }

            if (instanceCandidate instanceof Class) {
                instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
            }

            result = instanceCandidate;
            if (instanceCandidate instanceof NullBean) {
                if (this.isRequired(descriptor)) {
                    this.raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }

                result = null;
            }

            if (!ClassUtils.isAssignableValue(type, result)) {
                throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
            }

            Object var14 = result;
            return var14;
        }

        var7 = shortcut;
    } finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }

    return var7;
}

比较长,分析一下,我们看到中间有这一段:

Map matchingBeans = this.findAutowireCandidates(beanName, type, descriptor);

这段是根据beanName也就是Mapper接口类名,和type也就是SqlSessionFactory的class

得到候选的SqlSessionFactory的候选实例,之所以还需要Mapper接口类是因为需要做判断,注入的类里不能再引用自己。

如果得到的候选实例数量大于1,则需要判定具体用哪个实例,首先找有没有@primary的实例,其次按照@priority注解来筛选,也就是这段的作用:

if (matchingBeans.size() > 1) {
    autowiredBeanName = this.determineAutowireCandidate(matchingBeans, descriptor);
    if (autowiredBeanName == null) {
        if (!this.isRequired(descriptor) && this.indicatesMultipleBeans(type)) {
            result = null;
            return result;
        }

        result = descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
        return result;
    }

    instanceCandidate = matchingBeans.get(autowiredBeanName);
}

确定了唯一的实例后,此实例还没有被装配,下面调用以下代码装配:

if (instanceCandidate instanceof Class) {
    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}

此时的autowiredBeanName是sqlSessionFactory,type是org.apache.ibatis.session.SqlSessionFactory的class,resolveCandidate()方法的代码是:

public Object resolveCandidate(String beanName, Class requiredType, BeanFactory beanFactory) throws BeansException {
    return beanFactory.getBean(beanName);
}

这里的beanFactory是DefaultListableBeanFactory,于是下面进入了常规的Spring创建Bean的流程,此时的beanName是sqlSessionFactory。

Spring创建Bean的代码流程网上一大堆,以下省略无数步骤,直接来到AbstractAutowireCapableBeanFactory的createBeanInstance()方法:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    Class beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    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());
    } else {
        Supplier instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return this.obtainFromSupplier(instanceSupplier, beanName);
        } else if (mbd.getFactoryMethodName() != null) {
            return this.instantiateUsingFactoryMethod(beanName, mbd, args);
        } else {
            boolean resolved = false;
            boolean autowireNecessary = false;
            if (args == null) {
                Object var8 = mbd.constructorArgumentLock;
                synchronized(mbd.constructorArgumentLock) {
                    if (mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }

            if (resolved) {
                return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
            } else {
                Constructor[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
                    ctors = mbd.getPreferredConstructors();
                    return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
                } else {
                    return this.autowireConstructor(beanName, mbd, ctors, args);
                }
            }
        }
    }
}

此时RootBeanDefinition mbd的factoryMethodName是有值的,其值就是sqlSessionFactory,所以会调用this.instantiateUsingFactoryMethod()方法。

 

另外说一句,SqLSessionFactory类的BeanDefinition源自mybatis中定义的MybatisAutoConfiguration类,其中有这么一个方法:

@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    .....
}

所以MybatisAutoConfiguration被加载时,因为@Bean注解和@ConditionalOnMissingBean注解,SqlSessionFactory类的BeanDefinition也随之创建完成了,并且根据这个方法装配了SqlSessionFactory类的BeanDefinition的构造方法,参数,返回值等一系列信息。

 

言归正传,还是回到上面AbstractAutowireCapableBeanFactory的this.instantiateUsingFactoryMethod()方法:

protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    return (new ConstructorResolver(this)).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

其中生成了一个ConstructorResolver的实例,然后调用了instantiateUsingFactoryMethod()方法,方法很长,后面慢慢分析:

public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);
    String factoryBeanName = mbd.getFactoryBeanName();
    Object factoryBean;
    Class factoryClass;
    boolean isStatic;
    if (factoryBeanName != null) {
        if (factoryBeanName.equals(beanName)) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean reference points back to the same bean definition");
        }

        factoryBean = this.beanFactory.getBean(factoryBeanName);
        if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
            throw new ImplicitlyAppearedSingletonException();
        }

        factoryClass = factoryBean.getClass();
        isStatic = false;
    } else {
        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;
    }

    Method factoryMethodToUse = null;
    ConstructorResolver.ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;
    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    } else {
        Object[] argsToResolve = null;
        Object var13 = mbd.constructorArgumentLock;
        synchronized(mbd.constructorArgumentLock) {
            factoryMethodToUse = (Method)mbd.resolvedConstructorOrFactoryMethod;
            if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                argsToUse = mbd.resolvedConstructorArguments;
                if (argsToUse == null) {
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }

        if (argsToResolve != null) {
            argsToUse = this.resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
        }
    }

    if (factoryMethodToUse == null || argsToUse == null) {
        factoryClass = ClassUtils.getUserClass(factoryClass);
        Method[] rawCandidates = this.getCandidateMethods(factoryClass, mbd);
        List candidateList = new ArrayList();
        Method[] candidates = rawCandidates;
        int var15 = rawCandidates.length;

        for(int var16 = 0; var16 < var15; ++var16) {
            Method candidate = candidates[var16];
            if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                candidateList.add(candidate);
            }
        }

        if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
            Method uniqueCandidate = (Method)candidateList.get(0);
            if (uniqueCandidate.getParameterCount() == 0) {
                mbd.factoryMethodToIntrospect = uniqueCandidate;
                Object var37 = mbd.constructorArgumentLock;
                synchronized(mbd.constructorArgumentLock) {
                    mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                    mbd.constructorArgumentsResolved = true;
                    mbd.resolvedConstructorArguments = EMPTY_ARGS;
                }

                bw.setBeanInstance(this.instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
                return bw;
            }
        }

        candidates = (Method[])candidateList.toArray(new Method[0]);
        AutowireUtils.sortFactoryMethods(candidates);
        ConstructorArgumentValues resolvedValues = null;
        boolean autowiring = mbd.getResolvedAutowireMode() == 3;
        int minTypeDiffWeight = 2147483647;
        Set ambiguousFactoryMethods = null;
        int minNrOfArgs;
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        } else if (mbd.hasConstructorArgumentValues()) {
            ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
            resolvedValues = new ConstructorArgumentValues();
            minNrOfArgs = this.resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
        } else {
            minNrOfArgs = 0;
        }

        LinkedList causes = null;
        Method[] var21 = candidates;
        int var22 = candidates.length;

        int var23;
        for(var23 = 0; var23 < var22; ++var23) {
            Method candidate = var21[var23];
            Class[] paramTypes = candidate.getParameterTypes();
            if (paramTypes.length >= minNrOfArgs) {
                ConstructorResolver.ArgumentsHolder argsHolder;
                if (explicitArgs != null) {
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }

                    argsHolder = new ConstructorResolver.ArgumentsHolder(explicitArgs);
                } else {
                    try {
                        String[] paramNames = null;
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        if (pnd != null) {
                            paramNames = pnd.getParameterNames(candidate);
                        }

                        argsHolder = this.createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
                    } catch (UnsatisfiedDependencyException var30) {
                        if (this.logger.isTraceEnabled()) {
                            this.logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + var30);
                        }

                        if (causes == null) {
                            causes = new LinkedList();
                        }

                        causes.add(var30);
                        continue;
                    }
                }

                int typeDiffWeight = mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes);
                if (typeDiffWeight < minTypeDiffWeight) {
                    factoryMethodToUse = candidate;
                    argsHolderToUse = argsHolder;
                    argsToUse = argsHolder.arguments;
                    minTypeDiffWeight = typeDiffWeight;
                    ambiguousFactoryMethods = null;
                } else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight && !mbd.isLenientConstructorResolution() && paramTypes.length == factoryMethodToUse.getParameterCount() && !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
                    if (ambiguousFactoryMethods == null) {
                        ambiguousFactoryMethods = new LinkedHashSet();
                        ambiguousFactoryMethods.add(factoryMethodToUse);
                    }

                    ambiguousFactoryMethods.add(candidate);
                }
            }
        }

        if (factoryMethodToUse == null) {
            if (causes != null) {
                UnsatisfiedDependencyException ex = (UnsatisfiedDependencyException)causes.removeLast();
                Iterator var45 = causes.iterator();

                while(var45.hasNext()) {
                    Exception cause = (Exception)var45.next();
                    this.beanFactory.onSuppressedException(cause);
                }

                throw ex;
            }

            List argTypes = new ArrayList(minNrOfArgs);
            if (explicitArgs != null) {
                Object[] var42 = explicitArgs;
                var23 = explicitArgs.length;

                for(int var47 = 0; var47 < var23; ++var47) {
                    Object arg = var42[var47];
                    argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                }
            } else if (resolvedValues != null) {
                Set valueHolders = new LinkedHashSet(resolvedValues.getArgumentCount());
                valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
                valueHolders.addAll(resolvedValues.getGenericArgumentValues());
                Iterator var46 = valueHolders.iterator();

                while(var46.hasNext()) {
                    ValueHolder value = (ValueHolder)var46.next();
                    String argType = value.getType() != null ? ClassUtils.getShortName(value.getType()) : (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null");
                    argTypes.add(argType);
                }
            }

            String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "No matching factory method found: " + (mbd.getFactoryBeanName() != null ? "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") + "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. Check that a method with the specified name " + (minNrOfArgs > 0 ? "and arguments " : "") + "exists and that it is " + (isStatic ? "static" : "non-static") + ".");
        }

        if (Void.TYPE == factoryMethodToUse.getReturnType()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid factory method '" + mbd.getFactoryMethodName() + "': needs to have a non-void return type!");
        }

        if (ambiguousFactoryMethods != null) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Ambiguous factory method matches found in bean '" + beanName + "' (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousFactoryMethods);
        }

        if (explicitArgs == null && argsHolderToUse != null) {
            mbd.factoryMethodToIntrospect = factoryMethodToUse;
            argsHolderToUse.storeCache(mbd, factoryMethodToUse);
        }
    }

    Assert.state(argsToUse != null, "Unresolved factory method arguments");
    bw.setBeanInstance(this.instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
    return bw;
}

方法很长,基本意思就是通过beanName和BeanDefinition,获得执行构造方法的各种要素。所以方法先是创建了BeanWrapper实例,定义了一堆变量,后面的方法就比较明确的分为几个部分。

第一部分是获得class:

if (factoryBeanName != null) {
    if (factoryBeanName.equals(beanName)) {
        throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean reference points back to the same bean definition");
    }

    factoryBean = this.beanFactory.getBean(factoryBeanName);
    if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
        throw new ImplicitlyAppearedSingletonException();
    }

    factoryClass = factoryBean.getClass();
    isStatic = false;
} else {
    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;
}

因为factoryBeanName在BeanDefinition中已经有了,就是org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration,直接从DefaultListableBeanFactory中按名字获得。MybatisAutoConfiguration的开头有@Configuration注解,在DefaultListableBeanFactory早就注册过。

 

第二部分,获得构造的方法名,也就是这一段:

Method factoryMethodToUse = null;
ConstructorResolver.ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
if (explicitArgs != null) {
    argsToUse = explicitArgs;
} else {
    Object[] argsToResolve = null;
    Object var13 = mbd.constructorArgumentLock;
    synchronized(mbd.constructorArgumentLock) {
        factoryMethodToUse = (Method)mbd.resolvedConstructorOrFactoryMethod;
        if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
            argsToUse = mbd.resolvedConstructorArguments;
            if (argsToUse == null) {
                argsToResolve = mbd.preparedConstructorArguments;
            }
        }
    }

    if (argsToResolve != null) {
        argsToUse = this.resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
    }
}

mbd.resolvedConstructorOrFactoryMethod这个参数在BeanDefinition中也有,其值就是sqlSessionFactory方法,然后获取构造方法用到的参数,先从resolvedConstructorArguments参数获取,其中没值,然后从preparedConstructorArguments中获取,其值是DruidDataSourceWrapper实例。

 

第三部分是创建一个SqlSessionFactory实例并给BeanWrapper赋值。

后面的:

if (factoryMethodToUse == null || argsToUse == null) {
    ....
}

这段是没有显式构造法方法或无参构造用的,SqlSessionFactory用不上,代码直接来到最后的:

bw.setBeanInstance(this.instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));

其中

this.instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse)

就是创建SqlSessionFactory实例的方法,此时:

beanName 是sqlSessionFactory字符串。

mbd是SqlSessionFactory类的BeanDefinition。

factoryBean是MybatisAutoConfiguration实例。

factoryMethodToUse是sqlSessionFactory方法。

argsToUse是一个Object数组,只有一个元素,就是DruidDataSourceWrapper实例。

通过上面的参数,Spring就可以使用对应参数,调用对应的构造方法了。

(本文结束)

你可能感兴趣的:(框架,Java)