这是我参与更文挑战的第3天,活动详情查看: 更文挑战web
通常状况下,开源框架都会提供插件或其余形式的拓展点,供开发者自行拓展。这样的好处是显而易见的,一是增长了框架的灵活性。二是开发者能够结合实际需求,对框架进行拓展,使其可以更好的工做。以MyBatis为例,咱们可基于MyBatis插件机制实现分页、分表,监控等功能。因为插件和业务无关,业务也没法感知插件的存在。所以能够无感植入插件,在无形中加强功能sql
Mybatis做为一个应用普遍的优秀的ORM开源框架,这个框架具备强大的灵活性,在四大组件 (Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易用的插件扩展机制。Mybatis对持久层的操做就是借助于四大核心对象。MyBatis支持用插件对四大核心对象进行拦截,对mybatis来讲插件就是拦截器,用来加强核心对象的功能,加强功能本质上是借助于底层的 动态代理实现的,换句话说,MyBatis中的四大对象都是代理对象markdown
MyBatis所容许拦截的方法以下:mybatis
在四大对象建立的时候app
拦截框架
插件具体是如何拦截并附加额外的功能的呢?以ParameterHandler来讲post
public ParameterHandler newParameterHandler(MappedStatement mappedStatement,Object object, BoundSql sql, InterceptorChain interceptorChain){
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql);
parameterHandler = (ParameterHandler)
interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors)
{
target = interceptor.plugin(target);
}
return target;
}
复制代码
interceptorChain保存了全部的拦截器(interceptors),是mybatis初始化的时候建立的。调用拦截器链中的拦截器依次的对目标进行拦截或加强。interceptor.plugin(target)中的target就能够理解为mybatis 中的四大对象。返回的target是被重重代理后的对象ui
若是咱们想要拦截Executor的query方法,那么能够这样定义插件:url
@Intercepts({
@Signature(
type = Executor.class,
method = "query",
args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class}
)
})
public class ExeunplePlugin implements Interceptor {
//省略逻辑
}
复制代码
除此以外,咱们还需将插件配置到sqlMapConfig.xml中。spa
<plugins>
<plugin interceptor="com.lagou.plugin.ExamplePlugin"></plugin>
</plugins>
复制代码
这样MyBatis在启动时能够加载插件,并保存插件实例到相关对象(InterceptorChain,拦截器链) 中。待准备工做作完后,MyBatis处于就绪状态。咱们在执行SQL时,须要先经过DefaultSqlSessionFactory 创 建 SqlSession。Executor 实例会在建立 SqlSession 的过程当中被建立, Executor实例建立完毕后, MyBatis会经过JDK动态代理为实例生成代理类。这样,插件逻辑便可在 Executor相关方法被调用前执行。
以上就是MyBatis插件机制的基本原理.
但愿对各位小伙伴有所帮助