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进行了包装,所以才会打印四次“生成代理对象”。

标签: none

添加新评论