前言
探究MyBatis Plus提供的预定义CRUD接口的实现方式。
两种方式
MBP提供两种包含预定义CRUD的接口:
com.baomidou.mybatisplus.extension.service.IServicecom.baomidou.mybatisplus.core.mapper.BaseMapper
其中IService接口是针对业务逻辑层的封装,并提供了批处理操作。BaseMapper则是对DAO层CRUD的封装。
BaseMapper
BaseMapper的接口规范很简单,看代码就能明白,重点是了解MBP如何实现的BaseMapper。
在使用MyBatis的情况下,我们定义了Mapper接口,然后会在对应的XML文件中提供动态SQL及映射关系,或者直接在Mapper接口方法上添加注解,MyBatis将XML中的配置或者注解作为元数据进行解析,然后将解析后的SQL语句存至org.apache.ibatis.session.Configuration。MBP在MyBatis的基础上只做增强不做改变,则只要能够实现原pipeline将元数据解析成动态SQL存至org.apache.ibatis.session.Configuration即可。
MyBatis Plus的整体思路是使用自己的组件替换MyBatis中的组件,以实现自定义的逻辑。其中MybatisPlusAutoConfiguration类替代了MyBatis的自动配置类,这个类中包含MybatisPlusProperties属性。MybatisPlusProperties包含mapperLocations字段用于解析Mapper XML文件的位置,并汇总为Resource数组。
在MybatisPlusAutoConfiguration#sqlSessionFactory函数中,包含XML位置的Resource数组被设置到MybatisSqlSessionFactoryBean.mapperLocations下(MybatisSqlSessionFactoryBean也是MBP替换组件)。而后在MybatisSqlSessionFactoryBean#buildSqlSessionFactory函数中,XML文件被逐个读取并解析。
1 | if (this.mapperLocations != null) { |
其中XMLMapperBuilder在解析过程中会调用XMLMapperBuilder#bindMapperForNamespace方法。
1 | private void bindMapperForNamespace() { |
此时的configuration为MybatisSqlSessionFactoryBean传入的targetConfiguration,即MybatisConfiguration(MBP替换组件)。此时MybatisMapperRegistry#addMapper调用MybatisMapperRegistry#addMapper方法。
MybatisMapperRegistry也是一个MBP替换组件,继承并替换掉原本的MapperRegistry,其addMapper方法如下。
1 | public <T> void addMapper(Class<T> type) { |
最终调用MBP自定义的MybatisMapperAnnotationBuilder#parse方法,如下。
1 |
|
通过全局缓存工具GlobalConfigUtils获取ISqlInjector实例,调用ISqlInjector#inspectInject方法进行CRUD方法注入。在实现上,实际上是由AbstractSqlInjector实现了ISqlInjector接口,然后又由DefaultSqlInjector继承AbstractSqlInjector实现最终注入。
1 | // AbstractSqlInjector |
其中每一个函数都是继承了com.baomidou.mybatisplus.core.injector.AbstractMethod的类,包含一个inject注入方法。
IService
IService的实现在com.baomidou.mybatisplus.extension.service.impl.ServiceImpl。
IService依赖于Spring容器,而BaseMapper不依赖,原因是IService实例中会注入一个BaseMapper实例用于做CRUD操作,也就是上面的那一套。
IService还支持批量操作,这部分源码比较好看,调用链路是:com.baomidou.mybatisplus.extension.toolkit.SqlHelper#executeBatch -> org.apache.ibatis.session#flushStatements
参考文献
[1] https://blog.csdn.net/wjw465150/article/details/126896276
[2] https://blog.csdn.net/zzuhkp/article/details/120174101
后记
首发于 silencezheng.top,转载请注明出处。