zoukankan      html  css  js  c++  java
  • MyBatis(十)插件开发 之 开发自定义插件

    一、动态改变SQL运行的参数

      我们可以在目标方法放行前后,做非常多的事情,以到达动态修改 MyBatis 的运行流程。

      在上面的插件开发基础上,当我们测试要查询id为1号的员工时,实际从数据库查询3号员工。

      插件的实现:

    /**
     * 完成插件签名
     *      告诉MyBatis当前插件用用来拦截哪个对象的哪个方法
     */
    @Intercepts(
            {
                    @Signature(type = StatementHandler.class, method = "parameterize", args = java.sql.Statement.class)
            }
    )
    public class MyFirstPlugin implements Interceptor {
    
        /**
         * intercept:拦截
         *      拦截目标对象的目标方法的执行。
         * @param invocation
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            System.out.println("MyFirstPlugin...intercept:" + invocation.getMethod());
    
            //动态的改变一下SQL运行的参数,以前查询1号员工,实际从数据库查询3号员工
            System.out.println("当前拦截到的对象:" + invocation.getTarget());
            //拿到 PreparedStatementHandler ===> ParameterHandler ===>parameterObject
            Object target = invocation.getTarget();
            // 拿到target的元数据
            MetaObject metaObject = SystemMetaObject.forObject(target);
            Object value = metaObject.getValue("parameterHandler.parameterObject");
            System.out.println("sql 语句用的参数是:" + value);
            //修改完SQL语句要用的参数
            metaObject.setValue("parameterHandler.parameterObject", "3");
    
    
            //执行目标方法
            Object proceed = invocation.proceed();
    
            //返回执行后的返回值
            return proceed;
        }
    
        /**
         * plugin:包装
         *      包装目标对象的;包装,为目标对象创建一个代理对象
         * @param target
         * @return
         */
        @Override
        public Object plugin(Object target) {
            System.out.println("MyFirstPlugin...plugin:MyBatis将要包装的对象" + target);
            //借助Plugin的 wrap 方法来使用当前Interceptor 包装我们目标对象
            Object wrap = Plugin.wrap(target, this);
            //返回当前 target 创建的动态代理
            return wrap;
        }
    
        /**
         * setProperties:
         *      将插件注册时 property 属性设置进来
         * @param properties
         */
        @Override
        public void setProperties(Properties properties) {
            System.out.println("插件配置的信息" + properties);
        }
    }

      测试代码:

         @Test
         public void test1() throws IOException {
              //1、获取 sqlSessionFactory
              SqlSessionFactory sqlSessionFactory = getsqlSessionFactory();
    
              //2、获取 sqlSession 实例,能直接执行已经映射的 SQL 语句
              SqlSession sqlSession = sqlSessionFactory.openSession();
    
              try {
                   //3、获取接口的实现类对象
                   /**
                    * 推荐使用
                    * 会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
                    */
                   EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
                   Employee emp = employeeMapper.getEmpById(1);
                   System.out.println(emp);
              } finally {
                   sqlSession.close();
              }
         }

      运行结果:

       可以看到在测试程序中传入的参数是1,我们在插件中手动修改为了 3,MyBatis在传递参数的时候是插件中的值,而且也生效了。

      

      分析:如何修改参数的?

      ① 首先来看 StatementHandler 接口中的 parameterize() 方法,这是我们要拦截的方法,这也是来给参数赋值的方法;

      

      ② 然后是到 RoutingStatementHandler 里面的 方法,具体是由 delegate 来执行的:

      

       

         在它的构造器里面来给 delegate 赋值,我们用的默认都是 PREPARED,

      ③ 再看 PreparedStatementHandler 的 parameterize() 方法

      

         可以看到具体调用的是 parameterHandler的方法。

      ④ ParameterHandler 接口中的方法:

        

      ⑤ 默认的是实现是 DefaultParameterHandler 类:

        

         在ParameterHandler 中有以下的成员变量信息,

        

        获取如果我们要修改参数的时候,直接获取 paramterObject 对象,然后再重新赋值即可。

      注意:在使用插件时,一定要谨慎修改,因为这里可以触及到 MyBatis 的底层原理。

  • 相关阅读:
    [页面布局方式]
    padding and margin
    【浏览器中的页面】
    【浏览器的页面循环系统】
    Activity启动模式详解(二)--->singleTask
    finish、onDestory、System.exit的区别
    Androidndk开发打包时我们应该如何注意平台的兼容(x86,arm,arm-v7a)
    关于WifiManager的一些看法
    高效的找出两个List中的不同元素
    关于Activity的生命周期
  • 原文地址:https://www.cnblogs.com/niujifei/p/15312171.html
Copyright © 2011-2022 走看看