MyBatis插件的生命周期:包装和拦截
1、插件的生命周期
众所周知,MyBatis有四大核心对象:
(1)ParameterHandler:处理SQL的参数对象
(2)ResultSetHandler:处理SQL的返回结果集
(3)StatementHandler:数据库的处理对象,用于执行SQL语句
(4)Executor:MyBatis的执行器,用于执行增删改查操作
Mybatis插件原理就是:使用动态代理对以上四个目标对象进行包装,然后再有针对性的进行拦截,其生命周期分为包装和拦截。
2、关于包装的注意事项
一旦配置了插件,那么在四大对象创建的时候,每个创建出来的对象都不是直接返回的。即便我们只想拦截四大对象其中之一,也会将四大对象都进行包装的。见下面程序运行结果所示。
3、自定义插件的开发
@Intercepts(value =
{ @Signature(type = StatementHandler.class, // 确定要拦截的对象
method = "prepare", // 确定要拦截的方法
args =
{ Connection.class, Integer.class }// 拦截方法的参数
) })
public class MyInterceptor implements Interceptor
{
@SuppressWarnings("unused")
private Properties properties;
public Object intercept(Invocation invocation) throws Throwable
{
System.out.println("开始拦截.....");
Object proceed = invocation.proceed();
System.out.println("结束拦截.....");
return proceed;
}
public Object plugin(Object target)
{
System.out.println("生成代理对象....");
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties)
{
System.out.println(properties.get("who"));
this.properties = properties;
}
}
<plugins>
<plugin interceptor="cn.mybatis.mydemo.MyInterceptor">
<property name="who" value="MyInterceptor" />
</plugin>
</plugins>
运行结果:
生成代理对象....
生成代理对象....
生成代理对象....
生成代理对象....
开始拦截.....
DEBUG [cn.mybatis.mydemo.App.main()] - ==> Preparing: SELECT * from tb_person where id = ?
结束拦截.....
结果分析:
如上所示,即便想拦截StatementHandler类,也会生成四个包装对象,分别对ParameterHandler、ResultSetHandler、StatementHandler、Executor进行了包装,所以才会打印四次“生成代理对象”。