MyBatis笔记(七):插件

1、四大对象

1.1、四大对象

  • StatementHandler:处理sql语句预编译,设置参数等相关工作
  • ParameterHandler:处理传入参数集
  • ResultHandler:处理结果集
  • Executor:它是一个执行器,真正进行java与数据库交互的对象

1.2、四大对象创建要点

  • 每个创建出来的对象不是直接返回的,而是interceptorChain.pluginAll(parameterHandler);
  • 获取到所有的Interceptor(拦截器)(插件需要实现的接口);
  • 调用interceptor.plugin(target);
  • 返回target包装后的对象
  • 插件机制,我们可以使用插件为目标对象创建一个代理对象;
  • AOP(面向切面)我们的插件可以为四大对象创建出代理对象;
  • 代理对象就可以拦截到四大对象的每一个执行
public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
}

1.3、可拦截的方法

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

二、插件开发

2.1、开发步骤

  • 编写插件实现Interceptor接口,并使用 @Intercepts注解完成插件签名
  • 在全局配置文件中注册插件

2.2、举例

  • 拦截StatementHandler类的parameterize方法
  • 实现Interceptor接口
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import java.util.Properties;
@Intercepts({
        @Signature(type = StatementHandler.class, method = "parameterize", args = java.sql.Statement.class)
})
public class PluginTest1 implements Interceptor {
    /**
     * intercept:拦截
     * */
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("intercept:" + invocation.getMethod());
        Object target = invocation.getTarget();
        System.out.println("intercept:当前拦截到的对象:"+target);
        MetaObject metaObject = SystemMetaObject.forObject(target);
        Object value = metaObject.getValue("parameterHandler.parameterObject");
        System.out.println("intercept:sql语句中的参数是:"+value);
        metaObject.setValue("parameterHandler.parameterObject", 2);
        //执行目标方法
        Object proceed = invocation.proceed();
        //返回执行后的返回值
        return proceed;
    }

    //包装目标对象,为目标对象创建一个代理对象
    public Object plugin(Object o) {
        System.out.println("plugin:将要包装的对象:"+o);
        // TODO Auto-generated method stub
        Object wrap = Plugin.wrap(o, this);
        //返回为当前target创建的动态代理
        return wrap;
    }

    //将插件注册时的property属性设置进来
    public void setProperties(Properties properties) {
        System.out.println("setProperties:"+properties);
    }
}
  • 在全局配置文件注册插件,<plugins>标签按照dtd标准,位于<settings>之后、<environments>之前
    <plugins>
        <plugin interceptor="com.qdc.PluginTest1"></plugin>
        <!-- 可实现多个插件 -->
    </plugins>

三、插件原理

  • 按照插件注解声明,按照插件配置顺序调用插件plugin方法,生成被拦截对象的动态代理
  • 多个插件依次生成目标对象的代理对象,层层包裹,先声明的先包裹;形成代理链
  • 目标方法执行时依次从外到内执行插件的intercept方法
  • Interceptor接口:

  1. Intercept:拦截目标方法执行
  2. plugin:生成动态代理对象,可以使用MyBatis提供的Plugin类的wrap方法
  3. setProperties:注入插件配置时设置的属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值