diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java index 471647f89cf..d1c4db25c28 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPoint.java @@ -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"); * you may not use this file except in compliance with the License. @@ -219,10 +219,12 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, @Override @Nullable public String[] getParameterNames() { - if (this.parameterNames == null) { - this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod()); + String[] parameterNames = this.parameterNames; + if (parameterNames == null) { + parameterNames = parameterNameDiscoverer.getParameterNames(getMethod()); + this.parameterNames = parameterNames; } - return this.parameterNames; + return parameterNames; } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java b/spring-beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java index f526ab3cdcf..a98c6eb41b0 100644 --- a/spring-beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java @@ -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"); * 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. - * @param object object wrapped by this DirectFieldAccessor + * @param object the object wrapped by this DirectFieldAccessor */ public DirectFieldAccessor(Object object) { super(object); @@ -61,7 +61,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor { /** * Create a new DirectFieldAccessor for the given object, * 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 parent the containing DirectFieldAccessor (must not be {@code null}) */ @@ -92,8 +92,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor { @Override protected NotWritablePropertyException createNotWritablePropertyException(String propertyName) { PropertyMatches matches = PropertyMatches.forField(propertyName, getRootClass()); - throw new NotWritablePropertyException( - getRootClass(), getNestedPath() + propertyName, + throw new NotWritablePropertyException(getRootClass(), getNestedPath() + propertyName, matches.buildErrorMessage(), matches.getPossibleMatches()); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java b/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java index 501f7c7e39f..847da65a735 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/standard/SpelCompiler.java @@ -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"); * you may not use this file except in compliance with the License. @@ -63,18 +63,20 @@ import org.springframework.util.StringUtils; *

Individual expressions can be compiled by calling {@code SpelCompiler.compile(expression)}. * * @author Andy Clement + * @author Juergen Hoeller * @since 4.1 */ 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 Log logger = LogFactory.getLog(SpelCompiler.class); + // 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. private static final Map compilers = new ConcurrentReferenceHashMap<>(); + // The child ClassLoader used to load the compiled expression classes 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 * 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. * @param expression the expression to compile * @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. - * 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 * @return the expression call, or {@code null} if the decision was to opt out of * compilation during code generation @@ -150,7 +152,7 @@ public final class SpelCompiler implements Opcodes { // Create getValue() method mv = cw.visitMethod(ACC_PUBLIC, "getValue", "(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(); 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 - * 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 * at least some of the older variants can be garbage collected. - * @param name name of the class - * @param bytes bytecode for the class + * @param name the name of the class + * @param bytes the bytecode for the class * @return the Class object for the compiled expression */ @SuppressWarnings("unchecked") @@ -202,6 +204,7 @@ public final class SpelCompiler implements Opcodes { return (Class) this.ccl.defineClass(name, bytes); } + /** * Factory method for compiler instances. The returned SpelCompiler will * 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 - * components of the expression are not suitable for compilation or the data types - * involved are not suitable for compilation. Used for testing. - * @return true if the expression was successfully compiled + * Request that an attempt is made to compile the specified expression. + * It may fail if components of the expression are not suitable for compilation + * or the data types involved are not suitable for compilation. Used for testing. + * @param expression the expression to compile + * @return {@code true} if the expression was successfully compiled, + * {@code false} otherwise */ public static boolean compile(Expression expression) { return (expression instanceof SpelExpression && ((SpelExpression) expression).compileExpression()); @@ -256,18 +261,21 @@ public final class SpelCompiler implements Opcodes { super(NO_URLS, classLoader); } - int getClassesDefinedCount() { - return this.classesDefinedCount; - } - public Class defineClass(String name, byte[] bytes) { Class clazz = super.defineClass(name, bytes, 0, bytes.length); this.classesDefinedCount++; return clazz; } + + public int getClassesDefinedCount() { + return this.classesDefinedCount; + } } + /** + * An ASM ClassWriter extension bound to the SpelCompiler's ClassLoader. + */ private class ExpressionClassWriter extends ClassWriter { public ExpressionClassWriter() {