Mybatis源码(Sqlsession执行Mapper过程)
回顾:session创建大致过程
String resource="mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory factory=new SqlsessionFactoryBuilder.build();
Sqlsession session=factory.openSession();
具体过程:首先使用Xpathparse类(xpathApi)读取配置文件建立Configuration对象。以这个Configuration对象为参数传入build()方法,建立DefaultsessionFactory对象。这里的DefaultsessionFactory并没有读取Configuration配置,当调用里面的OpenSession方法就会转去调用opensessionFromSource(字面意思从resource里面打开),里面用configuration做了三件事:1.建立事务工厂 2.建立事务 3.建立Executer (这个对象是执行sql语句的)。最后把Executor和Configuration做为参数产生一个Session返回。
要得到一个bean需要使用getMapper获取接口对象
sqlSession.getMapper(?.class);
进入我们今天的主题:SqlSession执行Mapper过程
SqlSession执行Mapper过程拆解为4部分介绍:
- 首先介绍Mapper接口的注册过程。
- 然后介绍MappedStatement对象的注册过程。
- 接着介绍Mapper方法的调用过程。
- 最后介绍SqlSession执行Mapper的过程。
Mapper的注册过程
Mapper是一个接口,我们调用SqlSession对象getMapper()返回的到底是什么呢?
答:SqlSession对象的getMapper()方法返回的一定是某个类的实例。实际上getMapper()方法返回的是一个动态代理对象。MyBatis中通过MapperProxy类实现动态代理。
知道动态代理之前你需要能够手撕静态代理,jdk原生的动态代理正是对静态代理的进一步封装而已。
package com.Thread;
//静态代理模式
public class Make7 {
public static void main(String[] args) {
//仔细看看下面的代码与 Therad therad=new Thread( 实现runnable接口的类实例 );区别
complany complany=new complany(new You());
//发现Therad就是婚庆公司额外实现了一个satrt方法。
//而我们只需要考虑线程开始要干嘛(结婚时候干嘛)
//这就是静态代理模式
//优点:
//1.主角只需要完成自己的事件
//2.代理完成了主角干不成的事情
complany.HappyMarry();
}
}
//代理模式需要继承同一个接口
interface Marry{
void HappyMarry();
}
//你要结婚了
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("帅哥结婚了");
}
}
//你请了一个外包公司
class complany implements Marry{
//对你负责
private You you;
public complany(You you) {
this.you = you;
}
//这个婚庆公司帮你处理一切除了结婚以外的琐事
@Override
public void HappyMarry() {
before();
this.you.HappyMarry();
after();
}
private void before() {
System.out.println("布置现场");
}
private void after() {
System.out.println("收钱");
}
}
我们需要回顾一下动态代理:(两种)
1.原生的java动态代理
2.CGLIB动态代理
这里只介绍原生的jdk动态代理:(推荐一位博客友动态代理讲解,主要看看动态代理即可)
链接:https://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html
认识了动态代理以后:我们来认识三个类
- MapperProxy------>实现了invocationhander接口是执行类invoke(方法)中调用Executer来执行sql
- MapperProxyFactory-------->是一个根据mapper来创建代理类proxy.newinstence
- MapperRegistry-------->注册mapper把mapper.xml和proxy.newinstence()创建的联系起来
画图理解:

MappedStatement对象的注册
MyBatis通过MappedStatement类描述Mapper的SQL配置信息。
mappedStatements属性是一个Map对象,它的Key为Mapper SQL配置的Id
我们可以大概猜到MappedStatement里面放就是sql语句,这里我们并不多做讨论。
Mapper方法的调用
任何dao的最终都会经过下面这个方法
这里只有一个方法invoke方法{
获取mappermethod//这个对象能简单获取sql语句的所有信息,里面用的就是MappedStatement对象
MapperMethod类是对Mapper方法相关信息的封装
在MapperProxy类的invoke()方法中获取MapperMethod对象后,最终会调用MapperMethod类的execute()。
}
SqlSession执行Mapper的过程
终结:通过Mapper代理对象调用Mapper接口中定义的方法时,会执行MapperProxy类中的拦截逻辑,将Mapper方法的调用转换为调用SqlSession提供的API方法。在SqlSession的API方法中通过Mapper的Id找到对应的MappedStatement对象,获取对应的SQL信息,通过StatementHandler操作JDBC的Statement对象完成与数据库的交互,然后通过ResultSetHandler处理结果集,将结果返回给调用者。

浙公网安备 33010602011771号