MyBatis架构体图
从MyBatis代码实现的角度来看,MyBatis的主要的核心部件有以下几个:
- SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能
- Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
- StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
- ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所需要的参数,
- ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;
- TypeHandler 负责java数据类型和jdbc数据类型之间的映射和转换
- MappedStatement MappedStatement维护了一条
- SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
- BoundSql 表示动态生成的SQL语句以及相应的参数信息
- Configuration MyBatis所有的配置信息都维持在Configuration对象之中。
它们的关系如下图所示:
如果想要对这四大对象进行操作可以用插件实现拦截操作,故插件就是拦截器
它们都是sqlSession的底层类实现,也是插件能够拦截的四大对象。所以这里已经触及了MyBATIS的底层,动态代理,反射随时可以看到。了解他们的协作,是插件编写的基础之一,所以这是十分的重要。
第一步首先在Mybatis配置文件中配置拦截器插件
然后创建这两个拦截器:
拦截器1代码如下
package com.thit.interceptor;
import java.sql.Statement;
import java.util.Properties;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.plugin.Intercepts;
/**
*
* @author 79027
* 插件签名,告诉mybatis插件用来拦截那个对象的那个方法
*/
@Intercepts({
@Signature(type=ResultSetHandler.class,method="handleResultSets",args=Statement.class)
})
public class Myinterceptor1 implements Interceptor{
//拦截目标对象
public Object intercept(Invocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("拦截的对象是1:"+invocation.getTarget());
System.out.println("拦截方法是1:"+invocation.getMethod().toString());
System.out.println("拦截参数是1:"+invocation.getArgs().length);
//执行拦截对象真正的方法
Object o=invocation.proceed();
return o;
}
//包装目标对象 为目标对象创建动态代理
public Object plugin(Object target) {
// TODO Auto-generated method stub
System.out.println("插件方法1--将要包装的目标对象1:"+target);
//为当前对象创建代理对象
Object o=Plugin.wrap(target, this);
return o;
}
//获取插件初始化参数
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
String value1=(String) properties.get("shuxing1");
String value2=(String) properties.get("shuxing2");
System.out.println("插件初始化参数1:"+value1+":"+value2);
}
}
拦截器2代码如下:
package com.thit.interceptor;
import java.sql.Statement;
import java.util.Properties;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.plugin.Intercepts;
/**
*
* @author 79027
* 插件签名,告诉mybatis插件用来拦截那个对象的那个方法
*/
@Intercepts({
@Signature(type=ResultSetHandler.class,method="handleResultSets",args=Statement.class)
})
public class Myinterceptor2 implements Interceptor{
//拦截目标对象 多个插件的时候按照 从后到前的顺序执行
public Object intercept(Invocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("拦截的对象是2:"+invocation.getTarget());
System.out.println("拦截方法是2:"+invocation.getMethod().toString());
System.out.println("拦截参数是2:"+invocation.getArgs().length);
//执行拦截对象真正的方法
Object o=invocation.proceed();
return o;
}
//包装目标对象 为目标对象创建动态代理 按照从前到后的顺序执行
public Object plugin(Object target) {
// TODO Auto-generated method stub
System.out.println("插件方法2--将要包装的目标对象2:"+target);
//为当前对象创建代理对象
Object o=Plugin.wrap(target, this);
return o;
}
//获取插件初始化参数
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
String value1=(String) properties.get("shuxing1");
String value2=(String) properties.get("shuxing2");
System.out.println("插件初始化参数2:"+value1+":"+value2);
}
}
void getAllpersion1() {
System.out.println("--------查询全部---------");
SqlSession sqlSession = dbtools.getSession();
PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
//分页
//第二种,Mapper接口方式的调用,推荐这种使用方式。
Page
通过测试代码的输出结果,我么可以看到
插件初始化参数1:value1:value11
插件初始化参数2:value2:value22
插件方法1--将要包装的目标对象1:org.apache.ibatis.executor.CachingExecutor@6f7fd0e6
插件方法2--将要包装的目标对象2:org.apache.ibatis.executor.CachingExecutor@6f7fd0e6
当前页码:1
总记录数:0
每页的记录数:10
总页码:0
插件方法1--将要包装的目标对象1:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@72967906
插件方法2--将要包装的目标对象2:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@72967906
插件方法1--将要包装的目标对象1:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@4f83df68
插件方法2--将要包装的目标对象2:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@4f83df68
插件方法1--将要包装的目标对象1:org.apache.ibatis.executor.statement.RoutingStatementHandler@7d8995e
插件方法2--将要包装的目标对象2:org.apache.ibatis.executor.statement.RoutingStatementHandler@7d8995e
拦截的对象是2:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@4f83df68
拦截方法是2:public abstract java.util.List org.apache.ibatis.executor.resultset.ResultSetHandler.handleResultSets(java.sql.Statement) throws java.sql.SQLException
拦截参数是2:1
拦截的对象是1:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@4f83df68
拦截方法是1:public abstract java.util.List org.apache.ibatis.executor.resultset.ResultSetHandler.handleResultSets(java.sql.Statement) throws java.sql.SQLException
拦截参数是1:1
插件方法1--将要包装的目标对象1:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@5b12b668
插件方法2--将要包装的目标对象2:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@5b12b668
插件方法1--将要包装的目标对象1:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@1165b38
插件方法2--将要包装的目标对象2:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@1165b38
插件方法1--将要包装的目标对象1:org.apache.ibatis.executor.statement.RoutingStatementHandler@4c12331b
插件方法2--将要包装的目标对象2:org.apache.ibatis.executor.statement.RoutingStatementHandler@4c12331b
拦截的对象是2:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@1165b38
拦截方法是2:public abstract java.util.List org.apache.ibatis.executor.resultset.ResultSetHandler.handleResultSets(java.sql.Statement) throws java.sql.SQLException
拦截参数是2:1
拦截的对象是1:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@1165b38
拦截方法是1:public abstract java.util.List org.apache.ibatis.executor.resultset.ResultSetHandler.handleResultSets(java.sql.Statement) throws java.sql.SQLException
拦截参数是1:1
集合长度:10
pageinfo总条数:144
pageinfo每页的记录数:10
pageinfo总页码:1
pageinfo总页码:15
Person [id=1, username=tom, [email protected], gender=F, dept=null]
Person [id=2, username=tom, [email protected], gender=F, dept=null]
Person [id=3, username=tom, [email protected], gender=F, dept=null]
Person [id=4, username=tom, [email protected], gender=F, dept=null]
Person [id=5, username=tom, [email protected], gender=F, dept=null]
Person [id=6, username=tom, [email protected], gender=F, dept=null]
Person [id=7, username=tom, [email protected], gender=F, dept=null]
Person [id=8, username=tom, [email protected], gender=F, dept=null]
Person [id=9, username=tom, [email protected], gender=F, dept=null]
Person [id=10, username=tom, [email protected], gender=F, dept=null]
---------结束---------