Mybatis底层源码执行流程详解
目录
2.重点解析UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
3.源码详解 UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
Mybatis底层源码执行流程详解
1.UserMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tarena.dao.UserMapper">
<!-- namespace必须为包名.接口名 -->
<!-- 根据id查询一个对象
id="findUserById" 必须接口中的方法名称
parameterType="java.lang.Integer" 必须对应接口方法参数类型
resultType="User" 必须对应接口中的方法的返回类型
-->
<select id="findUserById"
parameterType="java.lang.Integer"
resultType="User">
select
id,
username name,
userpassword password,
address
from
t_user
where id=#{id}
</select>
</mapper>
2.重点解析UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
package com.tarena.test;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.tarena.dao.UserMapper;
import com.tarena.entity.User;
import com.tarena.util.MyBatisUtil;
public class TestUserMapperClass {
@Test
public void testFindUserById(){
SqlSession sqlSession=null;
try{
sqlSession=MyBatisUtil.getSession();
//用UserMaper接口利用jdk动态代理生成接口儿子代理类,用代理生成代理对象
//用代理对象调用目标方法,实际上执行的是InvocationHandler中的invoke方法
//在invoke方法中调用selectOne等原生api方法,来做增删改查
// 接口类型 jdk动态代理对象=sqlSession.getMapper(接口类型.class);
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=userMapper.findUserById(7);
System.out.println(user);
sqlSession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
}finally{
sqlSession.close();
}
}
}
3.源码详解 UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
进去看源码的时候getMapper会传两个参数 一个sqlSession调用者 一个是 UserMapper接口的类信息
<T> 泛型 使用什么类 传什么类 当调用此方法会返回俩个参数 一个是 type 这是类型 为接口类型 this 就是谁调用就是谁(本类对象) sqlSession
接着往下传 mapperRegistry 注册 还是那两个值
创建一个代理工厂 缓存 如果有则直接从里面拿 如果没有则抛异常 代理工厂方法 把sqlsession 传进去
传进去三个参数 一个参数 一个接口 一个 方法缓存
三个参数 一个类加载器 (mapperIntface 就是传进去的Classl类型对象) 一个 接口数组 一个接口子实现 这个子实现接口一定调用了
public class MapperProxy<T> implements InvocationHandler, Serializable {
首先进入里面 这个就跟之前的动态代理相似了,但是我们没有使用目标代理类 代理方法 所有不会走 第一个if 判断method是不是代理类
也不走第二个if 判断是不是走的默认老方法 因为 我们就没有定义方法 所以关键点核心就在项目的execute 方法上 (下面的MaooerMethod 是缓存方法方面的 先不介绍)
execute 我们仿写的差不多 就是判断 方法 如何调用 根据 Sql 去解析XML 判断 存到 command.getType中 去一一判断
command.getName() 是获取节点ID的
后面的源码就不一一展示了
总结:最终会进入到invoke方法里 去逐一判断