MyBatis 执行流程及源码解析

简介: MyBatis 执行流程及源码解析

我们在日常工作中广泛使用mybatis作为数据持久层框架,但是mybatis的执行流程是怎么样的,你了解过吗。本文将从源码角度,带你分析mybatis的工作原理。

先看一个简单的例子,以Service调用Mapper接口为例:

public interface StudentMapper {
    @Select("select * from student")
    public List<Map<String,Object>> query();
}
@Service("studentService")
public class StudentServiceImpl implements StudentService {
    @Autowired
    StudentMapper studentMapper;
    @Override
    public List<Map<String, Object>> query() {
        return studentMapper.select();
    }
}

向Service中注入这个Mapper并调用时,你知道这时注入的是什么吗?

image.png

通过调试,可以知道这时实际的studentMapper是一个类型为MapperProxy的代理对象,下面将从myabtis环境初始化开始,具体分析代理对象的产生过程。(不熟悉代理对象的同学,可以查看之前专门讲java代理的文章)

一、配置SqlSessionFactoryBean 时都做了什么?

在进行spring和mybatis整合时,会用xml或者注解的方式去配置一个SqlSessionFactoryBean,本文中以注解方式为例:

@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
   SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
   sqlSessionFactoryBean.setDataSource(dataSource);
   return  sqlSessionFactoryBean;
}

看一下SqlSessionFactoryBean的继承实现关系:

image.png

先看spring中两个非常重要的接口,FactoryBean和InitializingBean。

FactoryBean:

FactoryBean是一个spring中比较特殊的Bean,通过它的getObject()方法可以返回一个对象实例。SqlSessionFactoryBean中getObject()方法的实现:

image.png

在这里用于创建并返回一个SqlSessionFactory,在 spring +mybatis 的环境下,我们使用SqlSessionFactoryBean来充当SqlSessionFactory。

InitializingBean:

InitializingBean接口中只有一个方法,afterPropertiesSet(),所有实现了接口的类,在bean的初始化之前都要调用这个方法。可以看出在上面的getObject方法中,如果SqlSessionFactory为空,会调用这个方法创建SqlSessionFactory

image.png

通过调用SqlSessionFactoryBuilder的build方法,最终返回了一个DefaultSqlSessionFactory实例,这个DefaultSqlSessionFactory中保存了一个非常重要的Configuration对象。

二、@MapperScan都做了什么?

在注解配置mybatis时,通过@MapperScan指定Mapper存放的包,就能自动为我们把接口实现成类。那么这是怎么实现的呢?

点开@MapperScan的源码,发现上面还有一行非常重要的注解:

@Import(MapperScannerRegistrar.class)

image.png

ImportBeanDefinitionRegistrar接口提供registerBeanDefinitions方法向用户暴露了BeanDefinitionRegistry,也就是说可以让用户手动创建BeanDefinition并使用该注册器注册到spring容器中。

查看MapperScannerRegistrar的方法registerBeanDefinitions中的核心代码

ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
……
scanner.doScan(StringUtils.toStringArray(basePackages));

主要是创建了一个Mapper扫描器,开启扫描。

ClassPathMapperScanner中doScan方法:

image.png

这里对生成的mapper的bean定义做了进一步处理

进入processBeanDefinitions()方法:

image.png

注意画框代码及上方的注释,先看一下从BeanDefinitionHolder获得BeanDefinition时beanClass初始的值:

image.png

等待setBeanClass执行完毕:

image.png

通过definition.setBeanClass()把原来的BeanClass的类型替换成了MapperFactoryBean类型。到这,完成了Mapper接口加载定义阶段中非常重要的一步,而这也是生成代理对象MapperProxy的关键。

三、mybatis如何生成代理对象?

看一下MapperFactoryBean的继承关系:

image.png

MapperFactoryBean继承的SqlSessionDaoSupport类实现了InitializingBean接口,那么我们还是首先找afterPropertiesSet()方法:

image.png

DaoSupport中,最终调用MapperFactoryBean中的方法:

image.png

首先通过获取sqlSession获得了非常重要的配置类Configuration,然后查看一下addMapper方法,最终调用的是MapperRegistry的addMapper方法:

image.png

红框中的代码为我们创建了Mapper 的代理工厂对象(还不是Mapper的代理对象),并把它放入了knownMappers这个Map中。

image.png

在这一步,只是简单初始化了MapperProxyFactory,把我们自己的mapper的类型传给了它,还并没有真正产生代理对象。

MapperRegistry并在之后的parse()方法中完成了xml文件的解析,每一个sql方法都被解析成了一个MappedStatement对象,并添加到了配置类Configuration对象中。

MapperFactoryBean最终返回了什么?

因为MapperFactoryBean实现了FactoryBean接口,所以我们看看getObject方法究竟返回了什么:

image.png

最终调用MapperRegistry的getMapper方法:

image.png

这里调用的了mybatis刚才生成的MapperProxyFactory,帮助我们实例化并返回了一个代理对象。MapperProxyFactory中使用newInstance方法,实例化MapperProxy,用于生成代理

image.png

至此,我们已经弄明白了文章开头的MapperProxy是如何生成的。

四、MapperProxy代理对象如何执行sql语句?

在StudentServiceImpl中的query方法中打一个断点跟踪语句,你会发现实际执行的就是代理类MapperProxy中的invoke()方法。

image.png

MapperProxy在作为代理类的同时,自身实现了InvocationHandler接口,所以invoke方法就是真正执行的代理逻辑。

image.png

在这里最终调用了MapperMethod的execute方法实际去执行了sql语句。

image.png

在该方法中,根据sql语句执行类型,调用sqlSession对应的方法执行并将结果返回给用户。至此,mybatis在spring环境下一次调用全部完成。


相关文章
|
3月前
|
人工智能 Java 数据库连接
Mybatis执行流程
本文详细分析了 MyBatis 的执行流程,介绍了其核心组件如 SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession 的作用与实现原理,并通过源码解析了 SQL 语句的执行过程,包括动态代理、缓存机制及数据库查询的实现,帮助读者深入理解 MyBatis 的内部工作机制。
101 0
Mybatis执行流程
|
28天前
|
存储 域名解析 弹性计算
阿里云上云流程参考:云服务器+域名+备案+域名解析绑定,全流程图文详解
对于初次通过阿里云完成上云的企业和个人用户来说,很多用户不仅是需要选购云服务器,同时还需要注册域名以及完成备案和域名的解析相关流程,从而实现网站的上线。本文将以上云操作流程为核心,结合阿里云的活动政策与用户系统梳理云服务器选购、域名注册、备案申请及域名绑定四大关键环节,以供用户完成线上业务部署做出参考。
|
4月前
|
Java 数据库连接 API
Java 对象模型现代化实践 基于 Spring Boot 与 MyBatis Plus 的实现方案深度解析
本文介绍了基于Spring Boot与MyBatis-Plus的Java对象模型现代化实践方案。采用Spring Boot 3.1.2作为基础框架,结合MyBatis-Plus 3.5.3.1进行数据访问层实现,使用Lombok简化PO对象,MapStruct处理对象转换。文章详细讲解了数据库设计、PO对象实现、DAO层构建、业务逻辑封装以及DTO/VO转换等核心环节,提供了一个完整的现代化Java对象模型实现案例。通过分层设计和对象转换,实现了业务逻辑与数据访问的解耦,提高了代码的可维护性和扩展性。
168 1
|
3月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
119 0
|
7月前
|
SQL XML Java
一、MyBatis简介:MyBatis历史、MyBatis特性、和其它持久化层技术对比、Mybatis下载依赖包流程
一、MyBatis简介:MyBatis历史、MyBatis特性、和其它持久化层技术对比、Mybatis下载依赖包流程
264 69
|
6月前
|
SQL 存储 Java
Mybatis源码解析:详述初始化过程
以上就是MyBatis的初始化过程,这个过程主要包括SqlSessionFactory的创建、配置文件的解析和加载、映射文件的加载、SqlSession的创建、SQL的执行和SqlSession的关闭。这个过程涉及到了MyBatis的核心类和接口,包括SqlSessionFactory、SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、Configuration、SqlSession和Executor等。通过这个过程,我们可以看出MyBatis的灵活性和强大性,它可以很好地支持定制化SQL、存储过程以及高级映射,同时也避免了几
110 20
|
7月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
659 29
|
7月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
7月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
191 4
|
7月前
|
Java 关系型数据库 数据库连接
Javaweb之Mybatis入门程序的详细解析
本文详细介绍了一个MyBatis入门程序的创建过程,从环境准备、Maven项目创建、MyBatis配置、实体类和Mapper接口的定义,到工具类和测试类的编写。通过这个示例,读者可以了解MyBatis的基本使用方法,并在实际项目中应用这些知识。
166 11

推荐镜像

更多
  • DNS