Mybatis 源码编译 实现自定义 <if> 标签 test 判断逻辑

12 篇文章 0 订阅
5 篇文章 0 订阅

使用 Mybatis 框架时,我们经常使用 “<if test="email != null and email != ''">” 来进行非空判断,但感觉这种方式不够优雅,比如需要代码层面进行 trim 操作,如果把此逻辑加在 test 中只会使得 xml 更加冗长,那能不能让 test 内部调用 java 代码呢?可以的,可以使用 @ 符号实现,例如:“<if test="@org.apache.commons.lang3.StringUtils@isNotBlank(email)">”,但是包名太长,能不能这样呢:“<if test="isNotBlank(email)">”,启动报错,不符合语法,那如果就想这样写,还要满足语法呢?

思路就是在某个步骤拦截一下解析出来的 if 标签的 test 属性,将  “isNotBlank(email)” 手动替换成 “@org.apache.commons.lang3.StringUtils@isNotBlank(email)”,于是搜索了下 mybatis 的拦截器,发现如下所示代码貌似可以获取 sql:

@Component
@Intercepts({
        @Signature(
                type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class
        })
})
 
public class MySqlInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 方法一
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        //id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
        String id = mappedStatement.getId();
        //sql语句类型 select、delete、insert、update
        String sqlCommandType = mappedStatement.getSqlCommandType().toString();
        BoundSql boundSql = statementHandler.getBoundSql();
 
        //获取到原始sql语句
        String sql = boundSql.getSql();
        String mSql = sql;
        //TODO 修改自己的mySql 

        //通过反射修改sql语句
        Field field = boundSql.getClass().getDeclaredField("sql");
        field.setAccessible(true);
        field.set(boundSql, mSql);
        return invocation.proceed();
 
    }
}

但是获取到的 sql 是去掉 “<if” 等标签之后的,如果是简单的在后面加上 limit 实现自定义分页插件是可以的,但是实现我这个需求貌似不行,可能如果花时间继续探索兴许可以找到一个通过实现 mybatis 提供的接口解决的方案,但是由于时间有限,最重要的是想尝试一下修改 mybatis 源代码,我对 mybatis 的加载顺序不是很了解,但是我知道一定有类似 “String test = getAttr( "test" )” 的逻辑,如果能找到,那么判断一下 test 是否以 “isNotBlank” 开头,然后将其替换成 “@org.apache.commons.lang3.StringUtils@isNotBlank” 就可以了,但是类似 “String test = getAttr( "test" )” 的代码又在哪里呢?于是百度了下:

进入第一个全局搜索 "test",找到:

现在心里有底了,开始准备 mybatis源码:

ide 快捷键 ctrl + shift +r 搜索"XMLScriptBuilder",找到:

'

进入maven本地仓库目录寻找 源码,发现没有:

点击 "Download Sources"下载源码:

此时源码已经下载成功了:

解压源码jar

新建一个maven工程( 不要选择 create from  archetype  ),三维坐标按照下图中的 pom.properties 文件中的设置:

用上图中的 pom.xml替换掉新建的额工程中的pom.xml,并将源码目录下的 org 目录整个复制到工程中的 src/main/java 下,如下图所示:

修改源码:

然后 执行 mvn install,不出意外的话,此时 maven 本地仓库中的 mybatis-3.5.3.jar 已经替换成了 编译生成的jar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值