Polishing
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -219,10 +219,12 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
|||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public String[] getParameterNames() {
|
public String[] getParameterNames() {
|
||||||
if (this.parameterNames == null) {
|
String[] parameterNames = this.parameterNames;
|
||||||
this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
|
if (parameterNames == null) {
|
||||||
|
parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
|
||||||
|
this.parameterNames = parameterNames;
|
||||||
}
|
}
|
||||||
return this.parameterNames;
|
return parameterNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -52,7 +52,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new DirectFieldAccessor for the given object.
|
* Create a new DirectFieldAccessor for the given object.
|
||||||
* @param object object wrapped by this DirectFieldAccessor
|
* @param object the object wrapped by this DirectFieldAccessor
|
||||||
*/
|
*/
|
||||||
public DirectFieldAccessor(Object object) {
|
public DirectFieldAccessor(Object object) {
|
||||||
super(object);
|
super(object);
|
||||||
@@ -61,7 +61,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
|||||||
/**
|
/**
|
||||||
* Create a new DirectFieldAccessor for the given object,
|
* Create a new DirectFieldAccessor for the given object,
|
||||||
* registering a nested path that the object is in.
|
* registering a nested path that the object is in.
|
||||||
* @param object object wrapped by this DirectFieldAccessor
|
* @param object the object wrapped by this DirectFieldAccessor
|
||||||
* @param nestedPath the nested path of the object
|
* @param nestedPath the nested path of the object
|
||||||
* @param parent the containing DirectFieldAccessor (must not be {@code null})
|
* @param parent the containing DirectFieldAccessor (must not be {@code null})
|
||||||
*/
|
*/
|
||||||
@@ -92,8 +92,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
|||||||
@Override
|
@Override
|
||||||
protected NotWritablePropertyException createNotWritablePropertyException(String propertyName) {
|
protected NotWritablePropertyException createNotWritablePropertyException(String propertyName) {
|
||||||
PropertyMatches matches = PropertyMatches.forField(propertyName, getRootClass());
|
PropertyMatches matches = PropertyMatches.forField(propertyName, getRootClass());
|
||||||
throw new NotWritablePropertyException(
|
throw new NotWritablePropertyException(getRootClass(), getNestedPath() + propertyName,
|
||||||
getRootClass(), getNestedPath() + propertyName,
|
|
||||||
matches.buildErrorMessage(), matches.getPossibleMatches());
|
matches.buildErrorMessage(), matches.getPossibleMatches());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -63,18 +63,20 @@ import org.springframework.util.StringUtils;
|
|||||||
* <p>Individual expressions can be compiled by calling {@code SpelCompiler.compile(expression)}.
|
* <p>Individual expressions can be compiled by calling {@code SpelCompiler.compile(expression)}.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public final class SpelCompiler implements Opcodes {
|
public final class SpelCompiler implements Opcodes {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(SpelCompiler.class);
|
|
||||||
|
|
||||||
private static final int CLASSES_DEFINED_LIMIT = 100;
|
private static final int CLASSES_DEFINED_LIMIT = 100;
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(SpelCompiler.class);
|
||||||
|
|
||||||
// A compiler is created for each classloader, it manages a child class loader of that
|
// A compiler is created for each classloader, it manages a child class loader of that
|
||||||
// classloader and the child is used to load the compiled expressions.
|
// classloader and the child is used to load the compiled expressions.
|
||||||
private static final Map<ClassLoader, SpelCompiler> compilers = new ConcurrentReferenceHashMap<>();
|
private static final Map<ClassLoader, SpelCompiler> compilers = new ConcurrentReferenceHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
// The child ClassLoader used to load the compiled expression classes
|
// The child ClassLoader used to load the compiled expression classes
|
||||||
private ChildClassLoader ccl;
|
private ChildClassLoader ccl;
|
||||||
|
|
||||||
@@ -90,7 +92,7 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
/**
|
/**
|
||||||
* Attempt compilation of the supplied expression. A check is made to see
|
* Attempt compilation of the supplied expression. A check is made to see
|
||||||
* if it is compilable before compilation proceeds. The check involves
|
* if it is compilable before compilation proceeds. The check involves
|
||||||
* visiting all the nodes in the expression Ast and ensuring enough state
|
* visiting all the nodes in the expression AST and ensuring enough state
|
||||||
* is known about them that bytecode can be generated for them.
|
* is known about them that bytecode can be generated for them.
|
||||||
* @param expression the expression to compile
|
* @param expression the expression to compile
|
||||||
* @return an instance of the class implementing the compiled expression,
|
* @return an instance of the class implementing the compiled expression,
|
||||||
@@ -125,7 +127,7 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the class that encapsulates the compiled expression and define it.
|
* Generate the class that encapsulates the compiled expression and define it.
|
||||||
* The generated class will be a subtype of CompiledExpression.
|
* The generated class will be a subtype of CompiledExpression.
|
||||||
* @param expressionToCompile the expression to be compiled
|
* @param expressionToCompile the expression to be compiled
|
||||||
* @return the expression call, or {@code null} if the decision was to opt out of
|
* @return the expression call, or {@code null} if the decision was to opt out of
|
||||||
* compilation during code generation
|
* compilation during code generation
|
||||||
@@ -150,7 +152,7 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
// Create getValue() method
|
// Create getValue() method
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "getValue",
|
mv = cw.visitMethod(ACC_PUBLIC, "getValue",
|
||||||
"(Ljava/lang/Object;Lorg/springframework/expression/EvaluationContext;)Ljava/lang/Object;", null,
|
"(Ljava/lang/Object;Lorg/springframework/expression/EvaluationContext;)Ljava/lang/Object;", null,
|
||||||
new String[ ]{"org/springframework/expression/EvaluationException"});
|
new String[] {"org/springframework/expression/EvaluationException"});
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
CodeFlow cf = new CodeFlow(className, cw);
|
CodeFlow cf = new CodeFlow(className, cw);
|
||||||
@@ -187,11 +189,11 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a compiled expression class. Makes sure the classloaders aren't used too much
|
* Load a compiled expression class. Makes sure the classloaders aren't used too much
|
||||||
* because they anchor compiled classes in memory and prevent GC. If you have expressions
|
* because they anchor compiled classes in memory and prevent GC. If you have expressions
|
||||||
* continually recompiling over time then by replacing the classloader periodically
|
* continually recompiling over time then by replacing the classloader periodically
|
||||||
* at least some of the older variants can be garbage collected.
|
* at least some of the older variants can be garbage collected.
|
||||||
* @param name name of the class
|
* @param name the name of the class
|
||||||
* @param bytes bytecode for the class
|
* @param bytes the bytecode for the class
|
||||||
* @return the Class object for the compiled expression
|
* @return the Class object for the compiled expression
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -202,6 +204,7 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
return (Class<? extends CompiledExpression>) this.ccl.defineClass(name, bytes);
|
return (Class<? extends CompiledExpression>) this.ccl.defineClass(name, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method for compiler instances. The returned SpelCompiler will
|
* Factory method for compiler instances. The returned SpelCompiler will
|
||||||
* attach a class loader as the child of the given class loader and this
|
* attach a class loader as the child of the given class loader and this
|
||||||
@@ -222,10 +225,12 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request that an attempt is made to compile the specified expression. It may fail if
|
* Request that an attempt is made to compile the specified expression.
|
||||||
* components of the expression are not suitable for compilation or the data types
|
* It may fail if components of the expression are not suitable for compilation
|
||||||
* involved are not suitable for compilation. Used for testing.
|
* or the data types involved are not suitable for compilation. Used for testing.
|
||||||
* @return true if the expression was successfully compiled
|
* @param expression the expression to compile
|
||||||
|
* @return {@code true} if the expression was successfully compiled,
|
||||||
|
* {@code false} otherwise
|
||||||
*/
|
*/
|
||||||
public static boolean compile(Expression expression) {
|
public static boolean compile(Expression expression) {
|
||||||
return (expression instanceof SpelExpression && ((SpelExpression) expression).compileExpression());
|
return (expression instanceof SpelExpression && ((SpelExpression) expression).compileExpression());
|
||||||
@@ -256,18 +261,21 @@ public final class SpelCompiler implements Opcodes {
|
|||||||
super(NO_URLS, classLoader);
|
super(NO_URLS, classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getClassesDefinedCount() {
|
|
||||||
return this.classesDefinedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> defineClass(String name, byte[] bytes) {
|
public Class<?> defineClass(String name, byte[] bytes) {
|
||||||
Class<?> clazz = super.defineClass(name, bytes, 0, bytes.length);
|
Class<?> clazz = super.defineClass(name, bytes, 0, bytes.length);
|
||||||
this.classesDefinedCount++;
|
this.classesDefinedCount++;
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getClassesDefinedCount() {
|
||||||
|
return this.classesDefinedCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ASM ClassWriter extension bound to the SpelCompiler's ClassLoader.
|
||||||
|
*/
|
||||||
private class ExpressionClassWriter extends ClassWriter {
|
private class ExpressionClassWriter extends ClassWriter {
|
||||||
|
|
||||||
public ExpressionClassWriter() {
|
public ExpressionClassWriter() {
|
||||||
|
|||||||
Reference in New Issue
Block a user