Spring 源码学习 之 Mybatis 解析过程

在这里插入图片描述


Mybatis 也是遵循 JDBC 规范的。

nputStream in=Resource.setAsStream("sqlMapConfig,xml");
SqlSessionFactory sqlsessionfactory=new SqlSessionFactoryBuilder.build(in);
SqlSession sqlsession=sqlsessionfactory.opensession();

全局配置文件源码解析

    sqlMapConfig.xml 中 有 <configuration> </configuration> 节点,会被解析成 Configuration 类的对象,这个对象十分重要,它是全局的配置对象,保存的是 MyBatis 所有的配置文件和接口。
    先看 SqlSessionFactoryBuilder 的 build() 方法中,有个 XMLConfigBuilder,会先对 XML 文件进行解析 : parse() 解析每个子节点,得到一个 Configuration对象,然后再调用 build 方法,会返回一个默认的 DefaultsqlSessionFactory 。

    而如何解析 mappers 这个子节点呢? 是 mapperElement(XNode parent) 方法,先遍历子节点,mapper 的子节点有两种:<mappers> <mapper> / <package>【包】 </mappers>,会到相应的逻辑进行解析。

mapper配置文件源码解析

    如果是 节点,先获取属性,有 3 个,
<mapper resource> ... resource /或是 url / 或是class </mapper>.,只能配置一个。
    【包】:定义了所有的 mapper 都是在这个包下,而这个包还有 类、接口,当然还有 xml,所以 Mybatis 是调用 configuration 的 addMappers(mapperPackage),把 mappers 加到全局配置变量中,是从包中扫描内所有的类和接口,而不扫描 XML,接下来判断是否接口 isInterface(),只获取到接口,接下来会解析接口,具体是:先判断 isResourceLoaded( resource ),判断是否已经加载过,没有的话调用 loadResource(),这里的资源指的是 XML 资源。

SQL语句执行流程源码解析

    是在 configurationElement(XNode context)中有 sqlElement(context.evalNodes(/mapper/sql)),就能解析到 SQL 语句,然后接下来执行 buildStatementFromContext(context.evalNodes(select|insert|update|delete))

${} 与 #{}

(
#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;
$将传入的数据直接显示生成在 SQL 中。
)

    Mybatis 会把 SQL 语句先转化成 Sqlsource
    带 “#” 是静态的 Sqlsource ,在解析配置文件的时候把 #{ }替换成 “”,执行SQL 的时候会给 “?” 进行赋值,。
    SQL语句中带有 “${ }” 的是动态Sqlsource ,只要有一个 “$”,就会当成动态 Sqlsource,在解析配置文件的时候不会翻译成 “?”,仍保存原来的 SQL 语句,执行的时候才会给 “${ }” 替换成变量的值 ,而如果有 “#{ }“会经过
BoundSql boundSql=prepareStatement.getBoundSql(parameterObject); ,就会把”#{ }“改成”?”,(也就是说,只要有#{ }的话,解析时就变成"?"了),“${ }”会导致 SQL注入的。

    

SqlSessionFactory sqlsessionfactory=new SqlSessionFactory();
SqlSession sqlsession=sqlsessionfactory.openSession();

    这里返回的是 一个默认的 DefaultsqlSessionFactory ,然后会调用sqlsession 的 getmapper(UserMapper.class) 方法,会构造一个代理对象,后续调用代理对象的方法,有通过代理工厂 new 一个实例:mapperProxyFactory.newInstance(sqlsession)

mapperProxyFactory 中的源码:

protected T newInstance(MapperProxy<T> mapperProxy)
{
return(T) Proxy.newProxyInstance(mapperInterface.getClassLoader,new Class[ ] {mapperInterface},mapperProxy);
}

public T newInstance(SqlSession sqlSession)
{
funal MapperProxy<T> mapperProxy = new MrapperProxy<>(sqlSession,mapperInterface,methodCache);
}

    mapperProxy 是实现了 InvocationHandler 接口的,它有实现 invoke 方法。这个方法中正是实现了 SQL 的执行过程。
    会根据调用的方法,比如 select、delete、update、insert,会生成 MapperStatement 对象,每个对象对应一个 节点<select id>...</select>… …
    有个

 Object param=method.convertArgusToqlCommandParam(args);

    如果是多个参数,就会生成一个 map;
比如:
“arg0”=“123”;
“arg1”=“aa”;
“param”=“aa”;
“param2”=“123”;
    如果只有一个参数,只会返回一个值。

    对于不同类型的 参数,比如 String,有对应的 StringTypePeHandler (继承自 BaseTypeHandler ) 会调用 setString 方法,最后通过 doQuery() 方法,该方法中先要获取到 Configuration ,然后会去调用 prepareStatement ,就是在这个方法中完成 JDBC操作,其中有个 StatementHandler.parameterize(statement) 参数化。

    最后会执行 executeForMany (SqlSession sqlSession,Object[] args) ,args 表示执行时传入的值。


Mybatis 相关可移步

https://blog.csdn.net/weixin_41750142/article/details/104722898

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值