Mybatis(4)动态代理相关分析

本文详细介绍了MyBatis如何通过动态代理实现接口方法的调用,从创建SqlSessionFactory到获取SqlSession,再到动态生成MapperProxy工厂,解析了MyBatis动态代理的全过程。重点讨论了MyBatis动态代理与JDK动态代理的区别,包括接口传入、Class对象的传入以及方法调用的返回值等差异。
摘要由CSDN通过智能技术生成

mybatis接口没有实现类,实现动态代理的过程

mapper接口定义方法

public interface StudentMapper {
    Student getStudent(Integer id);
}

mapper.xml文件编写sql语句

<?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.ojbk.mapper.StudentMapper">
<!--    联合查询-->
    <select id="getStudent" resultMap="StudentClass">
        select s.* ,c.* from student s left join class c on s.cid=c.cid where s.sid=#{id}
    </select>
    <resultMap id="StudentClass" type="student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <association property="classroom" javaType="class">
            <id property="cid" column="cid"/>
            <result property="cname" column="cname"/>
        </association>
    </resultMap>
 </mapper>

mybatis核心配置文件及数据库设置省略

测试

public class myTest throws IOException {
        //1.读取核心配置文件
        InputStream in = Resources.getResourceAsStream("mybatisConfig.xml");
        //2.创建工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.取出sqlSession
         SqlSession sqlSession = factory.openSession(true);//自动提交事务
        //4.取出动态代理的对象,完成接口中方法的调用,实则是调用xml文件中相的标签的功能
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
       //5.调用接口中的方法
        Student student = studentMapper.getStudent(1);
        System.out.println(student);
        //6.关闭sqlSession
        sqlSession.close();
    }

代码分析

1.读取核心配置文件

 InputStream in = Resources.getResourceAsStream("mybatisConfig.xml");

在这里插入图片描述
主要是读取核心配置文件mybatisConfig.xml并将其放入bufferedInputStream。

2.创建工厂对象,完成数据库连接池与数据库间的连接。

(1)首先调用SqlSessionFactory工厂的builder方法

在这里插入图片描述

(2)调用 XMLConfigBuilder

在这里插入图片描述
在这里插入图片描述

1)首先调用父类BaseBuilder方法new一个Configuration对象

在这里插入图片描述
主要包含 :这三个类的初始化及赋值
(1)configuration 配置类
(2)typeAliasRegistry 类型别名注册器
(3)typeHandlerRegistry 类型处理器注册器
关于该父类的详解超链接
BaseBuilder解析

2)ReflectorFactory

点进去看的话,是一个判断和设置Mybatis反射类Reflector对象缓存的东西
在这里插入图片描述

3) ErrorContext

这个方法是mybatis用于相关的异常日志输出,可以得到异常是由谁在做什么的时候在哪个资源文件中发生的,执行的 SQL 是哪个,以及 java 详细的异常信息。
在这里插入图片描述
详解超链接
ErrorContext

4) 其他

下面几个就是一些属性设置,根据这个parsed的布尔值为false执行下面步骤 (3) 的解析获取。

(3) XNode对象 root解析

在这里插入图片描述
主要包含了数据库连接的相关信息

在这里插入图片描述
并最后将其返回给configuration对象

(4)根据configuration中内容new一个默认的sqlsessionFactory工厂对象

在这里插入图片描述

3.从factory工厂中取出一个sqlSession连接对象

可以设置事务的自动提交
在这里插入图片描述

4.mybatis动态代理

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
可以看到读取了StudentMapper接口类对象后,调用configuration对象的getMapper方法,再调用MapperRegistry注册器的getMapper方法,最终创建了一个MapperProxyFactory对象,即mapper类的动态代理工厂。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

可以发现mybatis这里使用的动态代理和jdk动态代理类proxy一样
区别在于:
(1)jdk动态代理的ClassLoader传入的是接口实现类
mybatis传入的是接口

mapperInterface

mybatis使用接口全限定名通过class#forName生成class对象,而这个对象类型就是接口
在这里插入图片描述

(2)jdk动态代理的Class中传入的是接口实现类对象的class,读取所有接口
mybatis的Class传入的是接口本身。

MapperProxy

实现了invocationHandler类和Serializable类
说明该类首先可以被缓存(Mybatis的缓存)
在这里插入图片描述
在这里插入图片描述在我们利用Mapper进行数据库的相关操作时会调用MapperProxy的invoke()方法,该方法先判断接口方法是否有实现类,如果有的话调用实现类的方法,如果没有的话,调用cachedInvoker的方法
区别(3)jdk动态代理调用的都是实现类的方法,返回的是实现类的值
mybatis没有实现类,因此返回的是invoke方法的返回值。
即mybatis实现接口的方法都在MapperProxy这invocationHandler类中实现。

sqlsession对象

在这里插入图片描述
可以看到MapperProxy实现接口中的方法又主要依靠封装再sqlsession对象中的MapperStatement对象实现。

总结:

JDK动态代理和mybatis动态代理的区别
(1)jdk动态代理的ClassLoader传入的是接口实现类。
mybatis传入的是接口。
(2)jdk动态代理的Class中传入的是接口实现类对象的class,读取所有接口
mybatis的Class传入的是接口本身。
(3)jdk动态代理调用的都是实现类的方法,返回的是实现类的值
mybatis没有实现类,因此返回的是invoke方法的返回值。即mybatis实现接口的方法都在MapperProxy这invocationHandler类中实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值