1. 插件原理简介
-
MyBatis 在四大对象的创建过程中,都会有插件进行介入。插件可以利用动态代理机制一层层的包装目标对象,而实现在目标对象执行目标方法之前进行拦截的效果。
- MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。
- 默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
-
Executor (update, query, flushStatements, commit, rollback,getTransaction, close, isClosed)
-
ParameterHandler (getParameterObject, setParameters)
-
ResultSetHandler (handleResultSets, handleOutputParameters)
-
StatementHandler (prepare, parameterize, batch, update, query)
- 插件原理
- 在四大对象创建的时候
- 每个创建出来的对象不是直接返回的,而是 interceptorChain.pluginAll(parameterHandler);
- 获取到所有的 Interceptor(拦截器)(插件需要实现的接口);调用 interceptor.plugin(target);返回target包装后的对象
- 插件机制,我们可以使用插件为目标对象创建一个代理对象;AOP(面向切面)
- 我们的插件可以为四大对象创建出代理对象;
- 代理对象就可以拦截到四大对象的每一个执行;
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
2. 插件的编写以及应用
1. 编写 Interceptor 的实现类,并且使用 @Intercepts 注解完成插件签名
@Intercepts(
{
@Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
})
public class MyFirstPlugin implements Interceptor{
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("MyFirstPlugin...intercept:"+invocation.getMethod());
Object target = invocation.getTarget();
System.out.println("当前拦截到的对象:"+target);
MetaObject metaObject = SystemMetaObject.forObject(target);
Object value = metaObject.getValue("parameterHandler.parameterObject");
System.out.println("sql语句用的参数是:"+value);
metaObject.setValue("parameterHandler.parameterObject", 11);
Object proceed = invocation.proceed();
return proceed;
}
@Override
public Object plugin(Object target) {
System.out.println("MyFirstPlugin...plugin:mybatis将要包装的对象"+target);
Object wrap = Plugin.wrap(target, this);
return wrap;
}
@Override
public void setProperties(Properties properties) {
System.out.println("插件配置的信息:"+properties);
}
}
2. 将写好的插件注册到全局配置文件中
<plugins>
<plugin interceptor="www.xq.mybatis.dao.MyFirstPlugin">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</plugin>
</plugins>
3. 运行截图

3. 总结
- 插件开发
- 编写插件实现Interceptor接口,并使用 @Intercepts 注解完成插件签名
- 在全局配置文件中注册插件
- 插件原理
- 按照插件注解声明,按照插件配置顺序调用插件plugin方法,生成被拦截对象的动态代理
- 多个插件依次生成目标对象的代理对象,层层包裹,先声明的先包裹;形成代理链
- 目标方法执行时依次从外到内执行插件的intercept方法。
- 多个插件情况下,我们往往需要在某个插件中分离出目标对象。可以借助MyBatis提供的SystemMetaObject类来进行获取最后一层的h以及target属性的值
- Interceptor 接口
- Intercept:拦截目标方法执行
- plugin:生成动态代理对象,可以使用MyBatis提供的Plugin类的wrap方法
- setProperties:注入插件配置时设置的属性
