问题描述
谁能告诉我代码有什么问题? 使用javassist插入代码时,显示错误“由以下原因引起:编译错误:;丢失”; 但是我仔细检查,没有;完全不见了。这里的javassist有什么限制吗?
Classpool cp = Classpool.getDefault();
cp.importPackage("com.MysqL.cj");
CtClass cc = cp.get(clzname);
CtMethod ms = cc.getDeclaredMethod(
"execute");
StringBuilder sb = new StringBuilder();
sb.append("String sql = ((PreparedQuery) this.query).getoriginalsql();");
sb.append("QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();\n" +
" for (BindValue o : bindings.getBindValues()) {\n" +
" sql = sql.replaceFirst(\"\\\\?\",new String(o.getByteValue()));\n" +
" }");
sb.append(
"System.out.println( sql);");
ms.insertBefore(sb.toString());
byteCode = cc.toBytecode();
解决方法
insertBefore的Javadoc说:
https://www.javassist.org/html/javassist/CtBehavior.html#insertBefore(java.lang.String)
参数:src-表示插入的字节码的源代码。 它必须是单个语句或块。
因此,将代码括在花括号中,使它成为单个块。
,我通过替换for循环解决了我的错误。
javaassit似乎不支持便捷的for循环,必须将其更改为for(int i = 0; i 感谢@kutschem,代码也需要用大括号括起来。ClassPool cp = ClassPool.getDefault();
cp.importPackage("com.mysql.cj");
CtClass cc = cp.get(clzname);
CtMethod ms = cc.getDeclaredMethod(
"execute");
ms.insertBefore("{\n" +
" String sql = ((PreparedQuery) this.query).getOriginalSql();\n" +
" QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();\n" +
" for (int i =0; i < bindings.getBindValues().length; i++ ) sql = sql.replaceFirst(\"\\\\?\",new String(bindings.getBindValues()[i].getByteValue()));\n" +
" System.out.println(sql);\n" +
" }");
byteCode = cc.toBytecode();
除了将代码包装成大括号(如 @kutschem 所述)外,我还为您提供了一个方法,使您可以更轻松地连接字符串,而无需使用StringBuilder
。作为积极的副作用,您还会得到换行符:
String codeToBeInserted = String.join("\n","{"," String sql = ((PreparedQuery) this.query).getOriginalSql();"," QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();"," for (BindValue o : bindings.getBindValues()) {"," sql = sql.replaceFirst(\"\\\\?\",new String(o.getByteValue()));"," }"," System.out.println(sql);","}"
);
System.out.println(codeToBeInserted);
String.join
从Java 8开始可用。控制台输出为:
{
String sql = ((PreparedQuery) this.query).getOriginalSql();
QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();
for (BindValue o : bindings.getBindValues()) {
sql = sql.replaceFirst("\\?",new String(o.getByteValue()));
}
System.out.println(sql);
}
对我来说,您的代码在语法上看起来还不错,尤其是replaceFirst
打算用固定值替换?
。