mybatis四大对象指的是:executor,statementHandler,parameterHandler和resultHandler对象。这四个对象在sqlSession内部共同协作完成sql语句的执行,同时也是我们自定义插件拦截的四大对象。
1、 Executor
sqlSession 首先会调用executor.query方法执行查询。
Executor有以下四种(均继承了BaseExecutor,可在spring文件bean中配置):
SimpleExecutor-简单的Executor,所有的数据库操作均委托给StatementHandler处理
BatchExecutor - 批量更新的Executor,使用jdbc的batchupdate方法,使用此Executor,需要手动执行SqlSession的flushStatements,立即执行sql。
ReuseExecutor-大体上与SimpleExecutor相同,只是根据sql缓存了jdbc的statement,遇到相同的sql时,省去了statement的创建,提高效率,但需要手动执行SqlSession的flushStatements,清除缓存
CachingExecutor - 在mapper中配置cache,对查询结果做缓存,其中缓存的key根据以下代码存数生成,建议最好不要用mybatis这个层次的缓存,一般业务层的缓存更实用,而且更容易控制
mybatis生产Executor的关键代码如下:
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
此处采用责任链与JDK动态代理模式结合的方式,遍历的Interceptor 即遍历mybatis的拦截器。责任链模式可理解为若干拦截器对象组成一条拦截链表,请求在这个拦截链表一直传递,直到链上的某一拦截器对象处理此请求,这一模式在servlet的Filter和Dubbo的Filter有用到。不同的是,mybatis责任链则是通过动态代理的方式,使用Plugin代理实际的Executor类,即plugin(plugin(…(executor)))。
public class Plugin implements InvocationHandler{
private Object target;
private Interceptor interceptor;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (满足代理条件) {
return interceptor.intercept(new Invocation(target, method, args));
}
return method.invoke(target, args);
}
//对传入的对象进行代理,可能是实际的Executor类,也可能是Plugin代理类
public static Object wrap(Object target, Interceptor interceptor) {
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
if (interfaces.length > 0) {
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
}
2、StatementHandler
Executor在doQuery时生成StatementHandler对象
在MyBatis实现了statementHandler的有四个类:
RoutingStatementHandler,这是一个封装类,它不提供具体的实现,只是根据Executor的类型,创建不同的类型StatementHandler。
SimpleStatementHandler,这个类对应于JDBC的Statement对象,用于没有预编译参数的SQL的运行。
PreparedStatementHandler 这个用于预编译参数SQL的运行。
CallableStatementHandler 它将实存储过程的调度。
statementHandler的主要方法:
prepare:编译sql
parameterize:prepare后设置参数
query/update:sql执行
基于StatementHandler对象定义的插件:
修改sql语句则在预编译SQL(prepare方法前)操作。
修改参数则在调用parameterize方法前修改逻辑。或者使用ParameterHandler来改造设置参数。
组装结果集则在query方法前后加入逻辑,或者使用ResultHandler来改造组装结果。
parameterHandler和resultHandler上述简单提到过,由于在mybatis自定义插件中也使用较少,这里不做详细阐述。
mybatis自定义插件的具体实现demo下一篇见
参考文章:https://blog.csdn.net/ykzhen2015/article/details/51690672
http://blue2048.iteye.com/blog/2173069
https://www.cnblogs.com/lizo/p/7503862.html