zoukankan      html  css  js  c++  java
  • mybatis插件开发初探

    运行流程:

    /**
     * 1、获取sqlSessionFactory对象:
     *         解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession;
     *         注意:【MappedStatement】:代表一个增删改查的详细信息
     * 
     * 2、获取sqlSession对象
     *         返回一个DefaultSQlSession对象,包含Executor和Configuration;
     *         这一步会创建Executor对象;
     * 
     * 3、获取接口的代理对象(MapperProxy)
     *         getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象
     *         代理对象里面包含了,DefaultSqlSession(Executor)
     * 4、执行增删改查方法
     * 
     * 总结:
     *     1、根据配置文件(全局,sql映射)初始化出Configuration对象
     *     2、创建一个DefaultSqlSession对象,
     *         他里面包含Configuration以及
     *         Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
     *  3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
     *  4、MapperProxy里面有(DefaultSqlSession);
     *  5、执行增删改查方法:
     *          1)、调用DefaultSqlSession的增删改查(Executor);
     *          2)、会创建一个StatementHandler对象。
     *              (同时也会创建出ParameterHandler和ResultSetHandler)
     *          3)、调用StatementHandler预编译参数以及设置参数值;
     *              使用ParameterHandler来给sql设置参数
     *          4)、调用StatementHandler的增删改查方法;
     *          5)、ResultSetHandler封装结果
     *  注意:
     *      四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);
     */

     首先要在mybatis全局配置文件中配置:

        <!--plugins:注册插件  -->
        <plugins>
            <plugin interceptor="com.gong.mybatis.dao.MyFirstPlugin">
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </plugin>
        </plugins>

    property为自定义的属性名和值。

    MyFirstPlugin.java

    package com.gong.mybatis.dao;
    
    import java.util.Properties;
    
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.plugin.Intercepts;
    import org.apache.ibatis.plugin.Invocation;
    import org.apache.ibatis.plugin.Plugin;
    import org.apache.ibatis.plugin.Signature;
    
    
    //完成插件签名,用于拦截哪个对象的哪个方法
    
    @Intercepts({
        @Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
    })
    public class MyFirstPlugin implements Interceptor {
        /**
         * intercept:拦截
         * */
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("myfirstplugin...intercept:"+invocation.getMethod());
            //执行目标方法
            Object proceed = invocation.proceed();
            //返回执行后的返回值
            return proceed;
        }
        
        //包装目标对象,为目标对象创建一个代理对象
        @Override
        public Object plugin(Object target) {
            System.out.println("-->myfirstplugin...plugin,将要包装的对象:"+target);
            // TODO Auto-generated method stub
            Object wrap = Plugin.wrap(target, this);
            //返回为当前target创建的动态代理
            return wrap;
        }
        
        //将插件注册时的property属性设置进来
        @Override
        public void setProperties(Properties properties) {
            // TODO Auto-generated method stub
            System.out.println("插件配置的信息:"+properties);
        }
    
    }

    我们进行测试:随便运行一个要测试的方法

    package com.gong.mybatis.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    
    import com.gong.mybatis.bean.Department;
    import com.gong.mybatis.bean.Employee;
    import com.gong.mybatis.dao.EmployeeMapper;
    import com.gong.mybatis.mapper.EmployeeMapperDynamicSql;
    
    public class TestMybatis5 {
        
        public SqlSessionFactory getSqlSessionFactory() throws IOException {
            String resource = "mybatis-config.xml";
            InputStream is = Resources.getResourceAsStream(resource);
            return new SqlSessionFactoryBuilder().build(is);
        }
    
        @Test
        public void test() throws IOException {
            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
            SqlSession openSession = sqlSessionFactory.openSession();
            
            try {
                EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
                Employee em = mapper.getEmpById(1);
                System.out.println(em);
            } finally {
                // TODO: handle finally clause
                openSession.close();
            }
        }
        
    }

    输出:

    插件配置的信息:{password=123456, username=root}
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.executor.CachingExecutor@23faf8f2
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@1563da5
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@34c4973
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.executor.statement.RoutingStatementHandler@7a765367
    DEBUG 01-23 12:59:28,739 ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ?   (BaseJdbcLogger.java:145) 
    myfirstplugin...intercept:public abstract void org.apache.ibatis.executor.statement.StatementHandler.parameterize(java.sql.Statement) throws java.sql.SQLException
    DEBUG 01-23 12:59:28,823 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
    DEBUG 01-23 12:59:28,850 <==      Total: 1  (BaseJdbcLogger.java:145) 
    Employee [id=1, lastName=dema, gender=1, email=dema@qq.com, dept=null]

    说明:执行sql方法时会调用四大对象,如果不是自己配置拦截的类型,就放过,否则就进行拦截。我们定义的插件是拦截StatementHandler类中的parameterize方法,其参数为java.sql.Statement。

    当有多个插件时是怎么运行的?

        <!--plugins:注册插件  -->
        <plugins>
            <plugin interceptor="com.atguigu.mybatis.dao.MyFirstPlugin">
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </plugin>
            <plugin interceptor="com.atguigu.mybatis.dao.MySecondPlugin"></plugin>
        </plugins>

    MySecondPlugin.java

    package com.gong.mybatis.dao;
    
    import java.util.Properties;
    
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.plugin.Intercepts;
    import org.apache.ibatis.plugin.Invocation;
    import org.apache.ibatis.plugin.Plugin;
    import org.apache.ibatis.plugin.Signature;
    
    @Intercepts(
            {
                @Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
            })
    public class MySecondPlugin implements Interceptor{
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            System.out.println("MySecondPlugin...intercept:"+invocation.getMethod());
            return invocation.proceed();
        }
    
        @Override
        public Object plugin(Object target) {
            // TODO Auto-generated method stub
            System.out.println("MySecondPlugin...plugin,要包装的对象:"+target);
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
            // TODO Auto-generated method stub
        }
    
    }

    结果:

    插件配置的信息:{password=123456, username=root}
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.executor.CachingExecutor@23faf8f2
    MySecondPlugin...plugin,要包装的对象:org.apache.ibatis.executor.CachingExecutor@23faf8f2
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@1563da5
    MySecondPlugin...plugin,要包装的对象:org.apache.ibatis.scripting.defaults.DefaultParameterHandler@1563da5
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@34c4973
    MySecondPlugin...plugin,要包装的对象:org.apache.ibatis.executor.resultset.DefaultResultSetHandler@34c4973
    -->myfirstplugin...plugin,将要包装的对象:org.apache.ibatis.executor.statement.RoutingStatementHandler@7a765367
    MySecondPlugin...plugin,要包装的对象:org.apache.ibatis.executor.statement.RoutingStatementHandler@7a765367
    DEBUG 01-23 13:21:17,640 ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ?   (BaseJdbcLogger.java:145) 
    MySecondPlugin...intercept:public abstract void org.apache.ibatis.executor.statement.StatementHandler.parameterize(java.sql.Statement) throws java.sql.SQLException
    myfirstplugin...intercept:public abstract void org.apache.ibatis.executor.statement.StatementHandler.parameterize(java.sql.Statement) throws java.sql.SQLException
    DEBUG 01-23 13:21:17,698 ==> Parameters: 1(Integer)  (BaseJdbcLogger.java:145) 
    DEBUG 01-23 13:21:17,731 <==      Total: 1  (BaseJdbcLogger.java:145) 
    Employee [id=1, lastName=dema, gender=1, email=dema@qq.com, dept=null]

    需要注意一点:插件会按配置的顺序依次拦截,但在执行时会先执行后配置的,因为相当于为第一个代理对象再进行代理。

  • 相关阅读:
    hdu 3832 Earth Hour
    hdu 2112 HDU Today
    hdu 2473 Junk-Mail Filter
    hdu 1558 Segment set
    5-2学习记录|5-3日
    看面经
    2020-5-1学习记录
    2020-4-30学习记录
    2020-4-27学习记录
    4.19日学习笔记
  • 原文地址:https://www.cnblogs.com/xiximayou/p/12230518.html
Copyright © 2011-2022 走看看