内容简介:hello~各位读者好,我是鸭血粉丝(大家可以称呼我为「阿粉」)。今天,阿粉带着大家来了解一下获取首先,我们还是回顾一下上篇文件的类容。先看下这个测试类,大家还有印象吗:上篇源码分析讲了 获取
hello~各位读者好,我是鸭血粉丝(大家可以称呼我为「阿粉」)。今天,阿粉带着大家来了解一下获取 mapper.xml 配置文件中的sql
1.上期回顾
首先,我们还是回顾一下上篇文件的类容。先看下这个测试类,大家还有印象吗:
public class MybatisTest {
@Test
public void testSelect() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
FruitMapper mapper = session.getMapper(FruitMapper.class);
Fruit fruit = mapper.findById(1L);
System.out.println(fruit);
} finally {
session.close();
}
}
}
上篇源码分析讲了 获取 mybatis 的 mapper 接口,它是一个代理类。这次,我们来了解下 获取 mapper.xml 配置文件中的sql。
2. 初始化做了什么事
阿粉其实第一篇的时候就已经讲过了 mybatis 的初始化,但是已经有一段时间了。这篇文章又正好要讲怎么获取 mapper.xml 里面的 sql,所有这里阿粉再简单说下 mapper.xml 的初始化。
2.1 mapper.xml
首先看下阿粉测试的 mapper.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.cl.mybatis.mapper.FruitMapper">
<sql id="fruit">id,name </sql>
<select id="findById" resultType="fruit">
select <include refid="fruit"/> from fruit where id =#{id}
</select>
</mapper>
2.2 Configuration -> mappedStatements
然后,所有解析的 xml 都会放到 Configuration 这个类里面。那么跟着阿粉来看下 mapper.xml 解析之后是个什么东西。
这里阿粉就直接给出结果,就不再次去走下初始化流程了。
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
.conflictMessageProducer((savedValue, targetValue) ->
". please check " + savedValue.getResource() + " and " + targetValue.getResource());
mappedStatements 是 Configuration 类里面的一个属性,这个就是用来放我们的 mapper.xml 里面的信息。我们来看下具体是怎么放的。
首先在 SqlSession session = sqlSessionFactory.openSession(); 这段代码打个断点,sqlSessionFactory 已经构建了,里面有一个 Configuration 属性。看下阿粉截的图。
mappedStatements 是一个map,key 等于 com.cl.mybatis.mapper.FruitMapper.findById ,这个是什么?是不是就是 mapper.xml 类的全路径,加上 <select> 标签的 id 。然后 value 是一个 MappedStatement 对象,每个 <select | update | insert | delete> 会解析成一个 MappedStatement 对象。 MappedStatement 对象里面有一个 sqlSource 属性,这个放的就是我们自己写的 sql 。
现在是不是很清楚了,只要我们获取到 com.cl.mybatis.mapper.FruitMapper.findById 这个 key,是不是就可以获取到对应的 sql,那怎么获取这个key呢?
3. 获取对应的key
3.1 代理类 -> h
还记得阿粉上一篇文章吗?获取 mapper 接口,返回的是一个代理对象,使用的是JDK的动态代理。看下创建代理类的方法。
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
mapperProxy 这个是我们的 h 类,h 类里面肯定有一个 invoke 方法。首先什么是 h 类?我们看下 newProxyInstance 方法。
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
。。。
}
实现 InvocationHandler 接口的类就是 h类。还是不懂的可以去看下 JDK 实现的动态代理模式,阿粉这里就不继续深入了。
3.2 获取 key
现在们去看下 h类里面的 invoke 方法。MapperProxy -> invoke
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
我们看下倒数第二行的 cachedMapperMethod 方法,ctrl + 左键点进去。
private MapperMethod cachedMapperMethod(Method method) {
return methodCache.computeIfAbsent(method, k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
看下这句代码 MapperMethod(mapperInterface,method,sqlSession.getConfiguration())) 我们来猜测一下,mapperInterface 是不是我们的 mapper 接口,这个能不能获取到 mapper 接口的全路径,method 是不是我们当前调用的方法 ,看下阿粉的测试方法:Fruit fruit = mapper.findById(1L) ,获取 findById() 这个方法的名字,就是 “findById”,一拼接就获取到了key,对不对?我们带正式一下,ctrl + 左键 MapperMethod。
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, mapperInterface, method);
}
在倒数第一行代码上打个断点。我们看下 command 这个成员变量。
看,我们的 key 是不是拿到了,那么 sql 是不是也拿到了。
总结
最后,阿粉在来梳理下这个流程:
-
mybatis初始化的时候,会将mapper.xml解析放到Configuration类的mappedStatements属性上。 -
mappedStatements是一个map ,它的 value 是一个对象,对象里面的一个属性存了我们写的 sql 语句。要想获取 value 必须找到对应的 key。 - 获取 key 是通过 JDK代理模式实现的,代理 mapper 接口,在执行这个接口的方法的时候,就会获取到当前接口的全路径和当前方法的名字。
好了,今天阿粉就讲到这里,下次阿粉会带着到家去了解一下,获取到 sql 之后,mybatis是怎么去执行 sql 的。我们下次 mybatis 源码分析再见。
以上所述就是小编给大家介绍的《mybatis系列之获取mapper.xml配置文件中的sql》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 6、如何获取配置中心的配置
- Nacos 源码分析(二):获取配置流程
- Spring Security 实现 antMatchers 配置路径的动态获取 原 荐
- 腾讯 Tars-Go 服务获取自定义模版(配置)值
- Spring Cloud-Feign使用时获取apollo配置失败问题
- ADO.NET获取数据(DataSet)同时获取表的架构实例
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
七步掌握业务分析
芭芭拉·A·卡克诺德 / 2010-9 / 49.00元
《七步掌握业务分析》内容简介:业务分析师是新兴的专业职务。在组织或项目中,业务分析师通过与项目干系人合作,采取一系列技术和知识,分析、理解组织或项目需求,并实现组织或项目目标,提出解决方案。《七步掌握业务分析》作者是国际业务分析协会(IIBA)的《业务分析知识体系指南》BABOK创作委员会的核心成员,全书结合BABOK的标准,以通俗易懂的语言阐述了业务分析的基本概念、任务与目标,介绍了从初级业务分......一起来看看 《七步掌握业务分析》 这本书的介绍吧!