先說下大體思路,Spring整合Mybatis,在Spring的初始化鏈中主要有以下幾個重要步驟:
1、obtainFreshBeanFactory方法負責解析MyBatis的服務層Bean,即:ServiceBean,因爲這些ServiceBean是通過註解@Service聲明的,通常會在ServiceBean中注入XxxMapper。——這是Spring的正常操作,本文就不貼代碼了。
2、invokeBeanFactoryPostProcessors方法負責調用Mybatis的後置處理器解析註冊Mapper Bean,代碼繼承關係:
MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor implements BeanFactoryPostProcessor
3、finishBeanFactoryInitialization方法實現Mapper Bean實例化,並對ServiceBean注入;
——解析mapper接口,生成bean
Spring invokeBeanFactoryPostProcessors方法委託PostProcessorRegistrationDelegate類進行後置處理器調用。
Spring: refresh()
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
org.springframework.context.support.PostProcessorRegistrationDelegate
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
// 這裏要注意,後面要拿registry去註冊,因爲後面掃描類的參數是ClassPathMapperScanner,它的構造參數是BeanDefinitionRegistry
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
// beanFactoryPostProcessors這時候還是空
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 可以取到mybatis的後置處理器,但是不屬於PriorityOrdered,所以這裏還不會調用
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 可以取到mybatis的後置處理器,但是不屬於Ordered,所以這裏也不會調用
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最後再來一次
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 看是否已經處理過了
if (!processedBeans.contains(ppName)) {
// 還沒處理
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// ★★★★★★ 最終調用後置處理 ★★★★★★
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
對於Mybatis來講,在初始化之前要首先完成註冊,即:要完成BeanDefinition的生成以及在BeanDefinitionRegistry中的註冊。
——進入Mybatis代碼
org.mybatis.spring.mapper.MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
// 這裏ClassPathMapperScanner繼承Spring:ClassPathBeanDefinitionScanner,由父類提供scan實現
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.registerFilters();
// 調用Spring父類掃描方法
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
這裏回到spring代碼,是要增強scan功能
org.springframework.context.annotation.ClassPathBeanDefinitionScanner
/**
* Perform a scan within the specified base packages.
* @param basePackages the packages to check for annotated classes
* @return number of beans registered
*/
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
// 子類有實現
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
/**
* Perform a scan within the specified base packages,
* returning the registered bean definitions.
* <p>This method does <i>not</i> register an annotation config processor
* but rather leaves this up to the caller.
* @param basePackages the packages to check for annotated classes
* @return set of beans registered if any for tooling registration purposes (never {@code null})
*/
// 這個方法會通過子類再調回來,因爲解析的是目錄下的接口,所有由Spring負責處理
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 首先定義一個Set集合,對象是BeanDefinitionHolder,後面拿這個對象去註冊
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
for (String basePackage : basePackages) {
// findCandidateComponents方法負責拿到mapper接口對應的BeanDefinition,這裏是ScannedGenericBeanDefinition
// 這個方法稍微複雜,要單獨來一講,不過裏面的邏輯要清楚
// 就是根據路徑解析得到BeanDefinition,包含Bean的各種描述信息
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
子類複寫了父類的doScan方法,所以上面的doScan會走到子類,走子類主要的目的是processBeanDefinition方法,這個方法會給BeanDefinition設置必要的參數,比如:BeanClass=this.mapperFactoryBean.getClass(),告訴Spring這個是工廠Bean,到時候生成實例的時候通過工廠去實例化,工廠就是MapperFactoryBean。
org.mybatis.spring.mapper.ClassPathMapperScanner extends ClassPathBeanDefinitionScanner
@Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 這一步又反調了父類的doScan,說白了,就是子類想增強父類的doScna方法
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
// 走完上一步,mapper對應的Bean Definition以及解析出來了
if (beanDefinitions.isEmpty()) {
logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
} else {
processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
// 對bean definition進行處理
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
for (BeanDefinitionHolder holder : beanDefinitions) {
definition = (GenericBeanDefinition) holder.getBeanDefinition();
if (logger.isDebugEnabled()) {
logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName()
+ "' and '" + definition.getBeanClassName() + "' mapperInterface");
}
// the mapper interface is the original class of the bean
// but, the actual class of the bean is MapperFactoryBean
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
// ★★★★★★ 設置BeanClass,mapperFactoryBean.getClass())
definition.setBeanClass(this.mapperFactoryBean.getClass());
definition.getPropertyValues().add("addToConfig", this.addToConfig);
boolean explicitFactoryUsed = false;
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
explicitFactoryUsed = true;
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
if (explicitFactoryUsed) {
logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
if (explicitFactoryUsed) {
logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
if (!explicitFactoryUsed) {
if (logger.isDebugEnabled()) {
logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
}
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
}
}
——到此,Mybatis的XxxMapper BeanDefinition就已經註冊好了,對應的就是Mapper接口。
——下面就是注入了
從上面分析可知Mybatis的Mapper Bean的BeanDefinition中,BeanClass是MapperFactoryBean,這就說明在注入的時候,一定是通過工廠Bean去創建具體的實例,所以在看代碼前就要先了解:mybatis獲取mapper bean(注入屬性)是通過工廠Bean獲取的,工廠Bean創建實例又是通過動態代理實現的,同時我們也知道,工廠Bean在Spring初始化過程中不會實例化,只有單例Bean會實例化。
簡單來講:mybatis的mapper bean是工廠bean,要給服務bean注入mapper bean,並不是直接拿這個mapper bean注入,【我要汽車,你不能給我一個工廠】,而應該用工廠bean動態代理出一個具體的bean給服務Bean,而這個動態代理對象就是最終的MapperProxy@xxxx。
業務代碼:
@Component
public class UserService implements IUserService {
@Autowired
private UserMapper userMapper;
@Override
public String getUserName(Long userId) throws Exception {
return userMapper.getUserName(userId);
}
}
OK,進入獲取代理bean的邏輯:
比較奇怪,憑什麼你mybatis就是動態代理,工廠不能直接new嗎?帶着疑問進一步看代碼。
不過這個調用鏈確實很長,我就不一一貼出來了,大致文字說明一下:
1 對服務Bean進行依賴注入 -> 2 注入對象是Mapper Bean -> 3 通過getBean方式獲取 -> 4 getBean得到MapperBeanDefinition之後生成實例。
前面三步就不看了,直接看第四步:
org.springframework.beans.factory.support.AbstractBeanFactory
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// xxxxxxxxx 此處刪除一萬字
// Create bean instance.
// 如果你對這幾行代碼屬性的話,說明基本能理解spring的初始化流程了
// 爲什麼走這段,因爲工廠是單例工廠
if (mbd.isSingleton()) {
// 這裏getSingleton當然是get到了工廠bean
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
// 這一步就是通過工廠bean實例化具體的bean,重點在這裏。。。。。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// xxxxxxxxx
}
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
// 如果不是工廠Bean報錯
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
// 這裏註釋很好懂,除非你就想要這個工廠Bean,但這裏的name顯然跟工廠名稱不符
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
// 先從緩存取,spring真是到處都是緩存。。。。。。。
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 到核心方法了。。。。
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
org.springframework.beans.factory.support.FactoryBeanRegistrySupport
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) { // 緩存不存在的
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (object != null && shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 這裏的factory就是MapperFactoryBean,註冊mapper的時候專門篡改的。。。
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
return object;
}
org.mybatis.spring.mapper.MapperFactoryBean
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
org.mybatis.spring.SqlSessionTemplate ——這個類是專門給Spring整合用的
@Override
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}
org.apache.ibatis.session.Configuration
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
org.apache.ibatis.binding.MapperRegistry
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
org.apache.ibatis.binding.MapperProxyFactory
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
終於出來了,你以爲結束了嗎? 待續。。。