MyBatis的解析和运行原理---学习笔记(三)

官方文档

运行分两大部分

1.读取配置文件,缓存到Configuration对象中,用来创建SqlSessionFactory

2.SqlSession执行过程

动态代理:JDK反射机制和CGLIB代理。用于为Mapper产生代理类,执行相关方法。

反射调用的最大好处是配置性大大提高,降低模块之间耦合

JDK动态代理
必须提供接口
代理类要求实现InvocationHandler接口
/* 
 * Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);//bind 产生代理对象
 * Object result = method.invoke(target,args);//反射调用方法

 */

CGLIB动态代理,开源框架CGLIB
代理类需要实现MethodInterceptor接口
/* 
 * //getInstance
 * Enhancer enhancer = new Enhancer();
 * enhancer.setSuperClass(this.target.getClass());
 * enhancer.setCallback(this);//设置回调方法
 * enhancer.create();//创建代理对象
 *
 * //intercept
 * Object result = proxy.invokeSuper(obj,args);//反射调用方法
 */
MyBatis通常在延迟加载的时候才会用到CGLIB的动态代理

构建SqlSessionFactory
采用构造模式(降低对象的复杂性),通过SqlSessionFactoryBuilder进行构建
a)通过XMLConfigBuilder解析XML配置,读取数据存入Configuration类中(单例,几乎所有配置都存在这里)

b)使用Configuration对象创建SqlSessionFactory. (使用DefaultSqlSessionFactory)

映射器内部组成
a)MappedStatement,保存映射器的一个节点(select|insert|delete|update)
b)SqlSource,提供BoundSql对象,是MappedStatement的一个属性,主要作用:根据参数和其他规则组装SQL

c)BoundSql,建立SQL和参数,常用属性SQL,parameterObject,parameterMappings

parameterObject:传递简单对象 如int->Integer,传递多个参数{ “1”:p1,"2":p2..."param1":p1,"param2":p2...}
parameterMappings:是一个List,每个元素都是ParamterMapping对象,包含属性、名称、表达式、javaType、jdbcType、typeHandler等
SQL:写在映射器里面的SQL语句

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSession包含查询、插入、更新、删除方法,旧版中常用,新版中推荐使用Mapper

Mapper映射是通过动态代理来实现的
MapperProxy<T> implements InvocationHandler,Serializable {....
if(Object.class.equals(method.getDeclaringClass())) { //判断mapper是不是一个类
  return method.invoke(this,args);
}
final MapperMethod = cachedMapperMethod(method); //如果是接口,生成MapperMethod对象
return mapperMethod.execute(sqlSession,args); //执行SQL,insert/update/delete/select

映射器的XML命名空间对应的是Mapper接口类的全路径
根据全路径,利用动态代理,采用命令模式,使用SqlSession接口的方法执行SQL查询


Mapper执行过程组件(SqlSession四大对象)
Executor,执行器,负责调度StatementHandler、ParameterHandler、ResultHandler等来执行对应的SQL
StatementHandler,核心,使用Statement(PrepareStatement)执行SQL
ParameterHandler,处理SQL参数
ResultHandler,对结果集(ResultSet)进行封装,并返回

Executor提供了查询/更新/相关的事务方法
a)SIMPLE,简易执行器,默认,new SimpleExecutor(this,transaction);
b)REUSE,重用预处理语句,new ReuseExecutor(this,transaction);
c)BATCH,针对批量专用的执行器,批量更新/重用语句,new BatchExecutor(this,transaction);
new CachingExecutor(executor);
interceptorChain.pluginAll(executor);//通过插件构建一层层的动态代理对象


SqlSession运行总结
SqlSession通过Executor创建StatementHandler
StatementHandler(通过RoutingStatementHandler--->(使用SimpleStatementHandler, PreparedStatementHandler, CallableStatement )),然后执行下面三个步骤:
a)prepared预编译SQL 
b)parameterize设置参数(启用ParameterHandler,实现类DefaultParameterHandler)

c)query/update执行SQL(启用ResultSetHandler,实现类DefaultResultSetHandler)

parameterize调用parameterHandler的setParameters方法去设置参数,而参数根据类型处理器typeHandler进行处理.
query/update是通过ResultHandler的handleResult方法封装结果,如果是update,它返回整数,否则就通过typeHandler处理结果类型,最后调用ObjectFactory组装对象并返回.

猜你喜欢

转载自blog.csdn.net/lovewebeye/article/details/79895154