Mybatis---06Mybatis配置文件浅析(四)

参考链接:深入理解Mybatis插件开发

1.plugins:与其称为Mybatis插件,不如叫Mybatis拦截器,更加符合其功能定位,实际上它就是一个拦截器,应用代理模式,在方法级别上进行拦截。

  1):支持拦截的方法

      执行器Executor(update、query、commit、rollback等方法);

      参数处理器ParameterHandler(getParameterObject、setParameters方法);

      结果集处理器ResultSetHandler(handleResultSets、handleOutputParameters等方法);

      SQL语法构建器StatementHandler(prepare、parameterize、batch、update、query等方法);

  2):作用场景

      分页功能:mybatis的分页默认是基于内存分页的(查出所有,再截取),数据量大的情况下效率较低,不过使用mybatis插件可以改变该行为,只需要拦截StatementHandler类的prepare方法,改变要执行的SQL语句为分页语句即可;

      公共字段统一赋值:一般业务系统都会有创建者,创建时间,修改者,修改时间四个字段,对于这四个字段的赋值,实际上可以在DAO层统一拦截处理,可以用mybatis插件拦截Executor类的update方法,对相关参数进行统一赋值即可;

      性能监控:对于SQL语句执行的性能监控,可以通过拦截Executor类的update, query等方法,用日志记录每个方法执行的时间;

      其它:其实mybatis扩展性还是很强的,基于插件机制,基本上可以控制SQL执行的各个阶段,如执行阶段,参数处理阶段,语法构建阶段,结果集处理阶段,具体可以根据项目业务来实现对应业务逻辑。

  3):小例子

      A:创建一个自定义插件类MyPlugins,实现接口org.apache.ibatis.plugin.Interceptor,在类上使用注解@Intercepts设置拦截的类,类里面的方法,以及方法里面的参数

@Intercepts({
        @Signature(
                type = Executor.class,
                method = "query",
                args = {
                        MappedStatement.class,
                        Object.class,
                        RowBounds.class,
                        ResultHandler.class
                })
})
public class MyPlugins implements Interceptor  {

    /**
     * 在此实现自己的拦截逻辑
     * @param invocation Invocation参数中拿到执行方法的对象,方法,方法参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget(); //被代理对象
        System.out.println(target);
        Method method = invocation.getMethod(); //代理方法
        System.out.println(method);
        Object[] args = invocation.getArgs(); //方法参数
        System.out.println(Arrays.toString(args));
        System.out.println("我在拦截前");
        // do something ...... 方法拦截前执行代码块
        Object result = invocation.proceed();
        System.out.println("我在拦截后");
        // do something .......方法拦截后执行代码块
        return result;
    }

    /**
     * 生成代理对象
     * @param target
     * @return
     */
    @Override
    public Object plugin(Object target) {
        return  Plugin.wrap(target, this);
    }

    /**
     * 设置一些属性变量
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
        //输出设置的配置参数
        Iterator iterator = properties.keySet().iterator();
        while (iterator.hasNext()){
            String keyValue = String.valueOf(iterator.next());
            System.out.println(properties.getProperty(keyValue));
        }
    }
}

      B:在mybatis配置文件mybatis-config.xml注册,并设置一些参数

 <plugins>
        <plugin interceptor="com.james.mybatis.plugins.MyPlugins">
            <property name="name" value="zhangsan"/>
        </plugin>
    </plugins>

      C:在测试类中测试:

public class Main {
    public static void main(String[] args) throws IOException {

        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //2.创建 SqlSessionFactory 的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.使用构建者创建工厂对象 SqlSessionFactory,在配置文件中设置的plugins标签参数在执行这个是被使用
        SqlSessionFactory factory = builder.build(in);
        //4.使用 SqlSessionFactory 生产 SqlSession 对象
        SqlSession session = factory.openSession();
        //5.使用 SqlSession 创建 dao 接口的代理对象
        IBookDao bookDao = session.getMapper(IBookDao.class);
        //6.使用代理对象执行查询所有方法,执行这个方法是会被自己实现的插件类进行拦截
        Book book = bookDao.selectById(1);
        System.out.println(book);
        //7.释放资源
        session.close();
        in.close();
    }
}

 

    

 

posted @ 2020-06-13 15:38  Jenne  阅读(162)  评论(0)    收藏  举报