mybatis mapper生成流程

mybatis提供了一種非常簡便的方式去訪問數(shù)據(jù)庫,定義接口和sql之后,就能自動幫你完成jdbc操作。這得益于它的mapper機(jī)制,本篇文章在于分析mapper的流程。

一、生成MapperProxyFactory對象

DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

從mybatis的官方示例代碼可以看到,mapper接口的加載是通過Configuration類的addMapper方法去實(shí)現(xiàn)的。

public <T> void addMapper(Class<T> type) {
    this.knownMappers.put(type, new MapperProxyFactory(type));
    MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
    parser.parse();
}

可以看到,這里創(chuàng)建了一個(gè)MapperProxyFactory對象,當(dāng)用戶調(diào)用getMapper方法時(shí),則會調(diào)用該factory生成一個(gè)基于jdk的代理

public T newInstance(SqlSession sqlSession) {
  final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
  return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
  return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

最終調(diào)用方法時(shí),則是通過MapperProxy的invoke方法完成邏輯調(diào)用。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  final MapperMethod mapperMethod = cachedMapperMethod(method);
  return mapperMethod.execute(sqlSession, args);
}

MapperProxy內(nèi)部由MapperMethod的execute完成方法調(diào)用,該方法調(diào)用sqlSession完成操作,即完成了mapper的封裝。

if (SqlCommandType.INSERT == command.getType()) {
  Object param = method.convertArgsToSqlCommandParam(args);
  result = rowCountResult(sqlSession.insert(command.getName(), param));
...

二、通過mapperProxyFactory生成Mapper接口的代理對象

mybatis提供了一個(gè)MapperProxyFactory類,通過調(diào)用該類的工廠方法newInstance就可以生成目標(biāo)mapper接口的代理對象。但是想使用spring自動注入的功能,還需要針對每個(gè)mapper接口創(chuàng)建一個(gè)FactoryBean添加到spring的factory中?;貞浺幌挛覀兪褂胢ybatis自動為mapper生成代理的使用方法:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="orj.worf.mybatis.mapper"/>
    <property name="annotationClass" value="org.springframework.stereotype.Repository"/>
</bean>

通過MapperScannerConfigurer配置了要掃描的包,以及一些注解過濾器(選配),來為mapper接口生成對應(yīng)的factoryBean,這個(gè)類實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor,在spring容器啟動的時(shí)候,該類掃描到符合條件的mapper接口,生成對應(yīng)的FactoryBean:MapperFactoryBean。詳細(xì)的流程如下:


mapper初始化.jpg

之后將mapper注入到對應(yīng)的業(yè)務(wù)類時(shí),spring會調(diào)用FactoryBean的getObject方法,該方法利用MapperProxyFactory生成mapper的代理對象,。

public T getObject() throws Exception {
  return getSqlSession().getMapper(this.mapperInterface);
}

...
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
return mapperProxyFactory.newInstance(sqlSession);

三、MapperProxyFactory的生成策略

第一小節(jié)中我們了解到了調(diào)用Configuration的getMapper方法來為mapper接口生成代理工廠對象MapperProxyFactory這一硬編碼方式。在實(shí)際使用mybatis mapper時(shí),它是怎么自動化給每個(gè)mapper調(diào)用getMapper方法的呢?這一切要從SqlSessionFactoryBean上得到答案。


SQLSessionFactoryBean.jpg

SqlSessionFactoryBean的afterPropertiesSet掃描mapperLocations下所有的xml映射,最后把xml中mapper標(biāo)簽定義的namespace即mapper接口,利用Configuration的getMapper方法為期生成MapperProxyFactory對象。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容