先上小结:
正文:
在前面的代码流程中,在@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
可以看到,方法一开始用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就可以使用对应参数,调用对应的构造方法了。
(本文结束)