插件简介
一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的好处是显而易见的,一是增加了框架的灵活性。二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作。以MyBatis为例,我们可基于MyBati s插件机制实现分页、分表,监控等功能。由于插件和业务 无关,业务也无法感知插件的存在。因此可以无感植入插件,在无形中增强功能
Mybati s作为一个应用广泛的优秀的ORM开源框架,这个框架具有强大的灵活性,在四大组件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易用的插 件扩展机制。Mybatis对持久层的操作就是借助于四大核心对象。MyBatis支持用插件对四大核心对象进 行拦截,对mybatis来说插件就是拦截器,用来增强核心对象的功能,增强功能本质上是借助于底层的 动态代理实现的,换句话说,MyBatis中的四大对象都是代理对象

允许拦截的方法如下:
执行器Executor (update、query、commit、rollback等方法);
SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等方 法);
参数处理器ParameterHandler (getParameterObject、setParameters方法);
结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等方法);
Mybatis插件原理
在四大对象创建的时候
1、每个创建出来的对象不是直接返回的,而是interceptorChain.pluginAll(parameterHandler);
2、获取到所有的Interceptor (拦截器)(插件需要实现的接口);调用 interceptor.plugin(target);返回 target 包装后的对象
3、插件机制,我们可以使用插件为目标对象创建一个代理对象;AOP (面向切面)我们的插件可 以
为四大对象创建出代理对象,代理对象就可以拦截到四大对象的每一个执行;
自定义插件实现
@Intercepts({
@Signature(type= Executor.class,
method ="query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class MyPlugin1implements Interceptor {
/*
拦截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法*/
@Override
public Objectintercept(Invocation invocation)throws Throwable {
System.out.println("对方法进行了增强....");
//原方法参数
Object[] args = invocation.getArgs();
//原方法
Method method = invocation.getMethod();
//目标对象
Object target = invocation.getTarget();
//这里我们将原来查询的1 改为3
Integer u= (Integer) args[1];
args[1]=3;
System.out.println(u);
return invocation.proceed(); //原方法执行
}
/*
主要为了把当前的拦截器生成代理存到拦截器链中*/
@Override
public Objectplugin(Object target) {
Object wrap = Plugin.wrap(target, this);
return wrap;
}
/*
获取配置文件的参数*/
@Override
public void setProperties(Properties properties) {
System.out.println("获取到的配置文件的参数是:"+properties);
}
}
配置文件:

测试结果如下:

源码分析
Plugin实现了InvocationHandler接口 所以最终执行的实际上是invoke方法:

4,在每次创建excutor时候


网友评论