先上小結:
- @Autowired註解生效。
- Spring開始爲@Autowired註解的Mapper創建動態代理。使用的是BeanFatory中註冊的BeanDefinition。
- Spring標準的創建動態代理流程,創建Mapper接口類的BeanWrapper,準備進行屬性注入。
- 準備給Mapper代理注入sqlSessionFactory和sqlSessionTemplate。
- Spring標準的創建動態代理流程,創建SqlSessionFactory的代理。使用的是SqlSessionFactory的BeanDefinition。SqlSessionFactory的BeanDefinition是MybatisAutoConfiguration類加載時,被@Bean註解和@ConditionalOnMissingBean註解創建完成的。
- 通過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<String> 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<Boolean>)
((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<Object>) () -> {
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<String> 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<String> 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<String> 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<String> 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<String, Object> 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<String, Object> 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<String, Object> 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<Method> 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<Method> 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<UnsatisfiedDependencyException> 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<String> 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<ValueHolder> 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就可以使用對應參數,調用對應的構造方法了。
(本文結束)