|
|
|
@ -36,6 +36,7 @@ import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
import org.springframework.util.ConcurrentReferenceHashMap; |
|
|
|
import org.springframework.util.ConcurrentReferenceHashMap; |
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* A SpelCompiler will take a regular parsed expression and create (and load) a class
|
|
|
|
* A SpelCompiler will take a regular parsed expression and create (and load) a class
|
|
|
|
@ -132,9 +133,9 @@ public final class SpelCompiler implements Opcodes { |
|
|
|
@Nullable |
|
|
|
@Nullable |
|
|
|
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) { |
|
|
|
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) { |
|
|
|
// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
|
|
|
|
// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
|
|
|
|
String clazzName = "spel/Ex" + getNextSuffix(); |
|
|
|
String className = "spel/Ex" + getNextSuffix(); |
|
|
|
ClassWriter cw = new ExpressionClassWriter(); |
|
|
|
ClassWriter cw = new ExpressionClassWriter(); |
|
|
|
cw.visit(V1_5, ACC_PUBLIC, clazzName, null, "org/springframework/expression/spel/CompiledExpression", null); |
|
|
|
cw.visit(V1_5, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null); |
|
|
|
|
|
|
|
|
|
|
|
// Create default constructor
|
|
|
|
// Create default constructor
|
|
|
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); |
|
|
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); |
|
|
|
@ -152,7 +153,7 @@ public final class SpelCompiler implements Opcodes { |
|
|
|
new String[ ]{"org/springframework/expression/EvaluationException"}); |
|
|
|
new String[ ]{"org/springframework/expression/EvaluationException"}); |
|
|
|
mv.visitCode(); |
|
|
|
mv.visitCode(); |
|
|
|
|
|
|
|
|
|
|
|
CodeFlow cf = new CodeFlow(clazzName, cw); |
|
|
|
CodeFlow cf = new CodeFlow(className, cw); |
|
|
|
|
|
|
|
|
|
|
|
// Ask the expression AST to generate the body of the method
|
|
|
|
// Ask the expression AST to generate the body of the method
|
|
|
|
try { |
|
|
|
try { |
|
|
|
@ -181,7 +182,7 @@ public final class SpelCompiler implements Opcodes { |
|
|
|
byte[] data = cw.toByteArray(); |
|
|
|
byte[] data = cw.toByteArray(); |
|
|
|
// TODO need to make this conditionally occur based on a debug flag
|
|
|
|
// TODO need to make this conditionally occur based on a debug flag
|
|
|
|
// dump(expressionToCompile.toStringAST(), clazzName, data);
|
|
|
|
// dump(expressionToCompile.toStringAST(), clazzName, data);
|
|
|
|
return loadClass(clazzName.replaceAll("/", "."), data); |
|
|
|
return loadClass(StringUtils.replace(className, "/", "."), data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|