Mybatis 内部执行原理概述
# 40.Mybatis 内部执行原理概述
Mybatis 内部原理:代理对象+execute 方法
Mybatis 在使用代理 dao 的方式实现增删改查时做什么事呢?只有两件事:
- 第一:创建代理对象
- 第二:在代理对象中调用 selectList 方法
虽然只有两件事,但如果要讲解每个类的作用,还是得花点功夫的,本文就是简单讲解下这两件事 更多关于代理对象的说明,其实我们在讲解 Servlet 的时候已经讲解过了
# 分析
执行的流程大致如下:
读取配置文件:用到的技术就是解析 XML 的技术。Mybatis 用的是 dom4j 解析 XML 技术,读取了数据库连接信息,mapper 映射信息,以及具体的要执行的 SQL 的信息。
根据配置文件的信息创建 Connection 对象:注册驱动,获取连接
获取预处理对象 PreparedSatement,此时需要 SQL 语句:
conn.prepareStatement(sql);
执行查询:
ResultSet resultSet = preparedStatement.executeQuery();
遍历结果集用于封装 List 并返回,伪代码如下:
List<E> list = new ArrayList(); while( resultSet.next() ){ E element = (E) Class.forName(配置里的全限定类名).newlnstance() /* 进行封装,把每个 rs 的内容都添加到 element 中,实体类属性和表中的列名是一致的。 此处使用反射封装,于是我们就可以把表的列名看成是实体类的属性名称。 就可以使用反射的方式来根据名称获取每个属性,并把值赋进去。 */ //把 elementa 入到 list 中 list.add(element); } return list;
1
2
3
4
5
6
7
8
9
10
11
12
13
要想让上述的步骤成功执行,我们需要给封装的方法提供两个信息:
第一个:连接信息
第二个:映射信息。包含了两部分
- 第一:执行的 SQL 语句
- 第二:封装结果的实体类全限定类名。这两个信息组合成一个对象,假设该对象为 Mapper
然后 Mybatis 可以根据 id 来获得该 mapper 对象,然后执行封装的方法。可以理解为是一个定义了一个 map:
Map<String, Mapper> map
其中 String 就是全限定类名 + 方法名的字符串,通过这个 key 可以获取到 mapper 对象,mapper 对象里存储了 SQL 语句,以及映射的实体类类名。
接下来,就是创建代理对象了
IUserDao userDao = session.getMapper(IUserDao.class);
而 getMapper 方法内部,也是通过动态代理来创建对象的,伪代码如下:
public <T> getMappser(Class <T> daoInterfaceClass){
Proxy.newProxyInstance(类加载器, 代理对象要实现的接口字节码数组, 增强的逻辑)
}
2
3
newProxyInstance 方法的参数分析:
- 类加载器:使用的是和被代理对象相同的类加载器
- 代理对象实现的接口:和被代理对象实现相同的接口
- 增强的逻辑:就是要增强的方法,该参数是一个 InvocationHandler 的接口,需要写一个实现类,在实现类里调用了 selectList 方法
更多关于代理对象的说明,其实我们在讲解 Servlet 的时候已经讲解过了: JavaWeb-Filter 案例 (opens new window),这里不再详细说明