标签:sql语句 eth apache catch params util handle fse sdn
Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的)。
Mybatis支持对Executor、StatementHandler、ParameterHandler和ResultSetHandler进行拦截。
插件的运行时的逻辑:
前面博客介绍过Executor是在openSession()的过程中被创建的。在调用Configuration的newExecutor()方法创建Executor时会进行以下操作。
|
|
每一个拦截器对目标类都进行一次代理,层层进行。
executor执行了多次plugin,第一次plugin后通过Plugin.wrap方法生成了第一个代理类,姑且就叫executorProxy1,这个代理类的target属性是该executor对象。第二次plugin后通过Plugin.wrap方法生成了第二个代理类,姑且叫executorProxy2,这个代理类的target属性是executorProxy1…这样通过每个代理类的target属性就构成了一个代理链。
|
|
拦截器Interceptor接口定义了三个方法:
intercept(): 内部要通过invocation.proceed()显式地推进责任链前进,也就是调用下一个拦截器拦截目标方法。plugin(): 用当前这个拦截器生成对目标target的代理,实际是通过Plugin.wrap(target,this) 来完成的,把目标target和拦截器this传给了包装函数。setProperties(): 用于设置额外的参数,参数配置在拦截器的Properties节点里。
|
|
生成拦截器代理对象是在Plugin.wrap()中完成的,Plugin本身实现了InvocationHandler(JDK代理实现)。
target: 被代理的目标类。interceptor: 对应的拦截器。signatureMap: 拦截器拦截的方法缓存。在Plugin代理对象的invoke()完成对目标类的方法调用。如果方法签名和拦截中的签名一致,就调用拦截器的拦截方法intercept(),传递的是一个Invocation对象。
|
|
Invocation对象保存了代理对象的目标类,执行的目标类方法以及传递给它的参数,真正执行目标类的方法调用是在Invocation中的proceed()方法。
所以代理对象的invoke()中调用拦截器的intercept(Invocation invocation)方法后,在该方法还必须调用invocation.proceed()方法才能使代理链继续执行下去。
|
|
详情参见:Mybatis 插件原理
Mybatis的分页功能是基于内存的分页,也就是查出所有记录再按照偏移量offset和limit取出结果。在大数据量的情况下不适用,下面两个插件都是通过拦截Executor等重写sql语句实现数据库的物理分页。
Mybatis 自身通过 RowBounds来完成内存分页的。
|
|
|
|
|
|
|
|
物理分页就是在SQL查询过程中实现分页,不同的数据库厂商,实现也会不同。MySql通过在sql语句中添加offset和limit实现。
分页插件实现,通过添加拦截器,对Executor进行拦截,然后重写sql:
详情参见:Mybatis 分页
标签:sql语句 eth apache catch params util handle fse sdn
原文地址:https://www.cnblogs.com/lijianming180/p/12247903.html