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()方法,执行自定义的逻辑

  • 相关阅读:
    codeforces 589G G. Hiring(树状数组+二分)
    树状数组的小总结
    virtualenv
    Redis备份与恢复
    Linux 网站相关
    MySQL文章参考
    动态执行表不可访问,本会话的自动统计被禁止 。 在执行菜单里你可以禁止统计,或在v$session,v$sesstat 和 v$statname 表里获得select权限
    app已损坏,打不开。你应该将它移到废纸篓
    macos系统用virtualbox安装Linux系统无法设
    Hadoop 分布式部署HDFS-hadoop用户部署
  • 原文地址:https://www.cnblogs.com/BlueStarWei/p/14130438.html
Copyright © 2011-2022 走看看