Mybatis自定义插件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38409944/article/details/82494624

Mybatis插件原理和执行流程

对四大对象和插件有了一定了解后,这里我就开始简单实现一个自定义插件,来拦截四大对象,实现拦截器功能。
步骤:

1. 编写Interceptor的实现类
2. 使用@Intercepts注解完成插件签名 说明插件的拦截四大对象之一的哪一个对象的哪一个方法
3. 将写好的插件注册到全局配置文件中

编写Interceptor的实现类(dao层)以及注解声明

注解参数:

type:拦截对象(四大对象之一)
method:拦截对象的方法
args:当前方法的参数列表

编写Interceptor的实现类:

@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 {
        // TODO Auto-generated method stub
        System.out.println("要拦截的方法"+invocation+invocation.getMethod());
        Object prObject = invocation.proceed();
        return prObject;
    }

    /**
     * 包装目标对象的:包装:为目标对象创建一个代理对象
     */
    @Override
    public Object plugin(Object target) {
        // TODO Auto-generated method stub
        System.out.println("包装的对象"+target.toString());
        Object wrap = Plugin.wrap(target, this);
        return wrap;
    }

    /**
     * setProperties:
     *      将插件注册时 的property属性设置进来
     */
    @Override
    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub
        System.out.println(properties);
    }

}

全局配置文件:

<plugins>
    <plugin interceptor="dao.MyfirstPlugin">
    <property name="root" value="jjc"/>
    <property name="pwdword" value="123456"/>
    </plugin>
</plugins>  

注意:
如果是 两个不同的插件对同一个对象的同一个方法进行拦截的时候
第一个插件的plugin方法的参数是未包装对象
第二个插件的plugin方法的参数是第一个插件包装后的对象

举一个栗子:当你查询id为2的内容 结果显示id为4的内容

查看id内容存放位置:
包装的对象org.apache.ibatis.executor.statement.RoutingStatementHandler@7c541c15
根据以上的内容知道创建的StatementHandler接口实现类是RoutingStatementHandler 是中间类
然后 找到这个类 :默认是PREPARED

case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        再进入PreparedStatementHandler类:
         @Override
  public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }
  parameterHandler是BaseStatementHandler的属性
  相当于parameterHandler是PreparedStatementHandler的属性

这个接口实现类是:DefaultParameterHandler

DefaultParameterHandler类中属性:

  Object parameterObject封装的就是参数值
  MappedStatement mappedStatement封装当前对象的增删改查详细信息的
  BoundSql boundSql封装sql的详细信息的

编写截目标对象的目标方法的执行:

  @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("要拦截的方法"+invocation+invocation.getMethod());
        //得到当前对象
        Object target = invocation.getTarget();
        System.out.println("拦截的对象:"+target);
        //拿到:StatementHandler==>ParameterHandler===>parameterObject
        //拿到target的元数据
        MetaObject metaobject = SystemMetaObject.forObject(target);
        Object value = metaobject.getValue("parameterHandler.parameterObject");
        System.out.println("当前参数值:"+value);
        //修改完sql语句要用的参数
        metaobject.setValue("parameterHandler.parameterObject", 4);
        //执行原来的方法
        Object prObject = invocation.proceed();
        return prObject;
    }

猜你喜欢

转载自blog.csdn.net/qq_38409944/article/details/82494624
今日推荐