本文共 2726 字,大约阅读时间需要 9 分钟。
org.apache.ibatis.executor.parameter.ParameterHandler
:处理SQL的参数对象
org.apache.ibatis.executor.resultset.ResultSetHandler
:处理SQL的返回结果集 org.apache.ibatis.executor.statement.StatementHandler
:数据库的处理对象,用于执行SQL语句 org.apache.ibatis.executor.Executor
:MyBatis的执行器,用于执行增删改查操作 与其称为Mybatis插件,不如叫Mybatis拦截器,更加符合其功能定位,实际上它就是一个拦截器,应用代理模式,在方法级别上进行拦截。
支持拦截的方法: 1、参数处理器ParameterHandler
(getParameterObject、setParameters方法); 2、结果集处理器ResultSetHandler
(handleResultSets、handleOutputParameters等方法); 3、SQL语法构建器StatementHandler
(prepare、parameterize、batch、update、query等方法); 4、执行器Executor
(update、query、commit、rollback等方法); 那么这些类上的方法都是在什么阶段被拦截的呢?为理解这个问题,我们先看段简单的代码(摘自mybatis源码中的单元测试SqlSessionTest类),来了解下典型的mybatis执行流程,如下代码所示:
源码分析只是加深理解,不想看的可以跳过直接看第三节的用法。
我们从四大对象的创建为入口,逐步分析整个插件的使用过程。
以StatementHandler
为例,找到它的源码: xxxStatementHandler
都继承了BaseStatementHandler
,所以我们直接看BaseStatementHandler
,观察它的构造方法: BaseStatementHandler
时,也顺带创建了ParameterHandler
和ResultSetHandler
,点进去看这两个对象的创建方法: InterceptorChain
的pluginAll
方法来创建的,进一步观察pluginAll
方法,如下: plugin
方法生成代理对象,注意生成代理对象重新赋值给target
,所以如果有多个拦截器的话,生成的代理对象会被另一个代理对象代理,从而形成一个代理链条,执行的时候,依次执行所有拦截器的拦截逻辑代码; 继续看这个plugin
方法: PaginationInterceptor
继续分析,它是分页拦截器,执行分页功能。找到上面看到的plugin
方法: plugin
方法里面根据target类型进行返回,如果是StatementHandler
类型的,就执行Plugin.wrap
方法,其实这就是一个包装方法,输入两个对象,一个的被代理对象,一个是PaginationInterceptor
自身。 继续看这个wrap
方法: Proxy.newProxyInstance
方法来生成代理对象。 由于真正去执行Executor
、ParameterHandler
、ResultSetHandler
和StatementHandler
类中的方法的对象是代理对象,所以在执行方法时,首先调用的是Plugin
类(实现了InvocationHandler
接口)的invoke
方法,如下:
Interceptor
接口的intercept
方法实现,一般需要用户自定义实现逻辑,其中有一个重要参数,即Invocation
类,通过改参数我们可以获取执行对象,执行方法,以及执行方法上的参数,从而进行各种业务逻辑实现,一般在该方法的最后一句代码都是invocation.proceed()
(内部执行method.invoke
方法),否则将无法执行下一个拦截器的intercept
方法。 以上逻辑对应的时序图如下,这里我们以执行executor
对象的query
方法为例,且假设有两个拦截器存在: 注册插件的方法有两种:
第一种:单纯使用Mybatis,在Mybatis的配置文件注册:第二种,和Spring整合的Mybatis,在Spring的配置文件中注册:
配置好了之后,Mybatis创建四大对象的时候会就会创建代理对象。实现相应的插件功能。
简单的说,mybatis插件就是对ParameterHandler
、ResultSetHandler
、StatementHandler
、Executor
这四个接口上的方法进行拦截,利用JDK动态代理机制,为这些接口的实现类创建代理对象,在执行方法时,先去执行代理对象的方法,从而执行自己编写的拦截逻辑,所以真正要用好mybatis插件,主要还是要熟悉这四个接口的方法以及这些方法上的参数的含义;
转载地址:http://bzf.baihongyu.com/