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<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就可以使用對應參數,調用對應的構造方法了。

(本文結束)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章