zoukankan      html  css  js  c++  java
  • Mybatis插件(拦截器)使用及源码追踪

    Mybatis插件本质上就是一个拦截器,其应用代理模式,在方法级别上进行拦截。Mybatis插件可以用于SQL语句日志打印、权限控制、分页等功能。

     
    MyBatis 允许使用插件来拦截的方法调用包括:
        Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
        ParameterHandler (getParameterObject, setParameters)
        ResultSetHandler (handleResultSets, handleOutputParameters)
        StatementHandler (prepare, parameterize, batch, update, query)
     
    Mybatis插件的使用
     
    使用Mybatis插件只需要两个步骤:1)创建拦截器实现类;2)在配置文件applicationContext.xml中注册拦截器。
     
    1,创建拦截器实现类
    package com.blueStarWei.interceptor;
    
    import org.apache.ibatis.executor.Executor;
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.plugin.Intercepts;
    import org.apache.ibatis.plugin.Invocation;
    import org.apache.ibatis.plugin.Signature;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    
    import java.sql.Statement;
    
    /**
    * MyBatis 允许使用插件来拦截的方法调用包括:
    *     Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    *     ParameterHandler (getParameterObject, setParameters)
    *     ResultSetHandler (handleResultSets, handleOutputParameters)
    *     StatementHandler (prepare, parameterize, batch, update, query)
    *
    *  拦截器顺序:
    *       Executor -> ParameterHandler -> StatementHandler -> ResultSetHandler
    *
    */
    @Intercepts({
            @Signature(type = Executor.class, method = "query", args = {MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class}),
            @Signature(type = StatementHandler.class, method = "query", args = {Statement.class,ResultHandler.class})
    })
    public class SqlInterceptor implements Interceptor {
    
        public Object intercept(Invocation invocation) throws Throwable {
            System.out.println("------------------------bengin query-----------");
            Object target = invocation.getTarget();
            if(target instanceof StatementHandler) {
                StatementHandler handler = (StatementHandler) target;
                String sql = handler.getBoundSql().getSql();
                Object param = handler.getParameterHandler().getParameterObject();
    
                System.out.println("sql : "+sql.replace("?",param+""));
            }else if(target instanceof  Executor){
                Object[] args = invocation.getArgs();
                MappedStatement mappedStatement  = (MappedStatement) args[0];
                String methodName = mappedStatement.getId();
                System.out.println("method : "+methodName);
    
                BoundSql boundSql = mappedStatement.getBoundSql(args[1]);
                String sql = boundSql.getSql();
                Object param = boundSql.getParameterObject();
                System.out.println("sql : "+sql.replace("?",param+""));
            }
            Object result = invocation.proceed();
            System.out.println("result : "+result);
            System.out.println("------------------------bengin end-----------");
            return result;
        }
    }

    2,配置applicationContext.xml

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <!--    指定*Mapper.xml位置-->
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
        <!--注册Mybatis插件-->
        <property name="plugins"  >
          <bean class="com.blueStarWei.interceptor.SqlInterceptor" />
        </property>
    </bean>

    Mybatis插件原理

    Mybatis插件采用的是代理模式+责任链模式,具体原理可以查看代理模式增强之路(代理+责任链模式)

    Mybatis插件源码追踪

    1, 服务启动阶段

    在创建SqlSessionFactory的时候,注册拦截器,即:将拦截器添加到集合(interceptorChain)中。

    创建执行处理器(Executor、StatementHandler、ParameterHandler、ResultSetHandler)并返回代理对象;

    深入追踪pluginAll()源码:该方法会遍历集合(interceptors),调用每个interceptor的plugin(target)方法,对代理元封装,生成包含非业务逻辑的代理对象:

     

     

    2,运行(CRUD)阶段

    调用自定义拦截器的intercept()方法,执行自定义的逻辑

  • 相关阅读:
    c++中stl函数的使用
    java 中String类的常见方法和StringBuffer类的使用
    c++模板类和模板函数
    c++简单工厂类的设计模式
    Android自定义的button按钮
    c++基类与派生类之间的转换
    Unity和Android结合出现Unabled to convert class into dex format
    jz2240用tftp下载程序步骤
    解决jz2440不能ping同主机问题
    android中的事件传递机制
  • 原文地址:https://www.cnblogs.com/BlueStarWei/p/14130438.html
Copyright © 2011-2022 走看看