diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java index cc0aa1fe908..d7fc989d44f 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java @@ -347,14 +347,14 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov // Second candidate we've found - ambiguous binding throw new AmbiguousBindingException("Binding of throwing parameter '" + this.throwingName + "' is ambiguous: could be bound to argument " + - throwableIndex + " or argument " + i); + throwableIndex + " or " + i); } } } if (throwableIndex == -1) { - throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName - + "' could not be completed as no available arguments are a subtype of Throwable"); + throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName + + "' could not be completed as no available arguments are a subtype of Throwable"); } else { bindParameterName(throwableIndex, this.throwingName); @@ -373,7 +373,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov if (this.returningName != null) { if (this.numberOfRemainingUnboundArguments > 1) { throw new AmbiguousBindingException("Binding of returning parameter '" + this.returningName + - "' is ambiguous, there are " + this.numberOfRemainingUnboundArguments + " candidates."); + "' is ambiguous: there are " + this.numberOfRemainingUnboundArguments + " candidates."); } // We're all set... find the unbound parameter, and bind it. @@ -429,7 +429,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov int numAnnotationSlots = countNumberOfUnboundAnnotationArguments(); if (numAnnotationSlots > 1) { throw new AmbiguousBindingException("Found " + varNames.size() + - " potential annotation variable(s), and " + + " potential annotation variable(s) and " + numAnnotationSlots + " potential argument slots"); } else if (numAnnotationSlots == 1) { @@ -486,7 +486,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov private void maybeBindThisOrTargetOrArgsFromPointcutExpression() { if (this.numberOfRemainingUnboundArguments > 1) { throw new AmbiguousBindingException("Still " + this.numberOfRemainingUnboundArguments - + " unbound args at this(),target(),args() binding stage, with no way to determine between them"); + + " unbound args at this()/target()/args() binding stage, with no way to determine between them"); } List varNames = new ArrayList<>(); @@ -520,7 +520,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov if (varNames.size() > 1) { throw new AmbiguousBindingException("Found " + varNames.size() + - " candidate this(), target() or args() variables but only one unbound argument slot"); + " candidate this(), target(), or args() variables but only one unbound argument slot"); } else if (varNames.size() == 1) { for (int j = 0; j < this.parameterNameBindings.length; j++) { @@ -646,8 +646,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov private void maybeBindPrimitiveArgsFromPointcutExpression() { int numUnboundPrimitives = countNumberOfUnboundPrimitiveArguments(); if (numUnboundPrimitives > 1) { - throw new AmbiguousBindingException("Found '" + numUnboundPrimitives + - "' unbound primitive arguments with no way to distinguish between them."); + throw new AmbiguousBindingException("Found " + numUnboundPrimitives + + " unbound primitive arguments with no way to distinguish between them."); } if (numUnboundPrimitives == 1) { // Look for arg variable and bind it if we find exactly one... diff --git a/spring-aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java b/spring-aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java index beb986e6f82..16f7b6b7d83 100644 --- a/spring-aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -17,7 +17,6 @@ package org.springframework.aop.aspectj; import java.lang.reflect.Method; -import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; @@ -43,17 +42,17 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void noArgs() { - assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]); + assertParameterNames(getMethod("noArgs"), "execution(* *(..))"); } @Test void joinPointOnly() { - assertParameterNames(getMethod("tjp"), "execution(* *(..))", new String[] {"thisJoinPoint"}); + assertParameterNames(getMethod("tjp"), "execution(* *(..))", "thisJoinPoint"); } @Test void joinPointStaticPartOnly() { - assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", new String[] {"thisJoinPointStaticPart"}); + assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", "thisJoinPointStaticPart"); } @Test @@ -64,18 +63,18 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void oneThrowable() { - assertParameterNames(getMethod("oneThrowable"), "foo()", null, "ex", new String[] {"ex"}); + assertParameterNamesExtended(getMethod("oneThrowable"), "foo()", null, "ex", "ex"); } @Test void oneJPAndOneThrowable() { - assertParameterNames(getMethod("jpAndOneThrowable"), "foo()", null, "ex", new String[] {"thisJoinPoint", "ex"}); + assertParameterNamesExtended(getMethod("jpAndOneThrowable"), "foo()", null, "ex", "thisJoinPoint", "ex"); } @Test void oneJPAndTwoThrowables() { assertException(getMethod("jpAndTwoThrowables"), "foo()", null, "ex", AmbiguousBindingException.class, - "Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or argument 2"); + "Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or 2"); } @Test @@ -86,13 +85,13 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void returning() { - assertParameterNames(getMethod("oneObject"), "foo()", "obj", null, new String[] {"obj"}); + assertParameterNamesExtended(getMethod("oneObject"), "foo()", "obj", null, "obj"); } @Test void ambiguousReturning() { assertException(getMethod("twoObjects"), "foo()", "obj", null, AmbiguousBindingException.class, - "Binding of returning parameter 'obj' is ambiguous, there are 2 candidates."); + "Binding of returning parameter 'obj' is ambiguous: there are 2 candidates."); } @Test @@ -103,22 +102,22 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void thisBindingOneCandidate() { - assertParameterNames(getMethod("oneObject"), "this(x)", new String[] {"x"}); + assertParameterNames(getMethod("oneObject"), "this(x)", "x"); } @Test void thisBindingWithAlternateTokenizations() { - assertParameterNames(getMethod("oneObject"), "this( x )", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "this( x)", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "this (x )", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "this(x )", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "foo() && this(x)", new String[] {"x"}); + assertParameterNames(getMethod("oneObject"), "this( x )", "x"); + assertParameterNames(getMethod("oneObject"), "this( x)", "x"); + assertParameterNames(getMethod("oneObject"), "this (x )", "x"); + assertParameterNames(getMethod("oneObject"), "this(x )", "x"); + assertParameterNames(getMethod("oneObject"), "foo() && this(x)", "x"); } @Test void thisBindingTwoCandidates() { assertException(getMethod("oneObject"), "this(x) || this(y)", AmbiguousBindingException.class, - "Found 2 candidate this(), target() or args() variables but only one unbound argument slot"); + "Found 2 candidate this(), target(), or args() variables but only one unbound argument slot"); } @Test @@ -131,22 +130,22 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void targetBindingOneCandidate() { - assertParameterNames(getMethod("oneObject"), "target(x)", new String[] {"x"}); + assertParameterNames(getMethod("oneObject"), "target(x)", "x"); } @Test void targetBindingWithAlternateTokenizations() { - assertParameterNames(getMethod("oneObject"), "target( x )", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "target( x)", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "target (x )", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "target(x )", new String[] {"x"}); - assertParameterNames(getMethod("oneObject"), "foo() && target(x)", new String[] {"x"}); + assertParameterNames(getMethod("oneObject"), "target( x )", "x"); + assertParameterNames(getMethod("oneObject"), "target( x)", "x"); + assertParameterNames(getMethod("oneObject"), "target (x )", "x"); + assertParameterNames(getMethod("oneObject"), "target(x )", "x"); + assertParameterNames(getMethod("oneObject"), "foo() && target(x)", "x"); } @Test void targetBindingTwoCandidates() { assertException(getMethod("oneObject"), "target(x) || target(y)", AmbiguousBindingException.class, - "Found 2 candidate this(), target() or args() variables but only one unbound argument slot"); + "Found 2 candidate this(), target(), or args() variables but only one unbound argument slot"); } @Test @@ -159,24 +158,24 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void argsBindingOneObject() { - assertParameterNames(getMethod("oneObject"), "args(x)", new String[] {"x"}); + assertParameterNames(getMethod("oneObject"), "args(x)", "x"); } @Test void argsBindingOneObjectTwoCandidates() { assertException(getMethod("oneObject"), "args(x,y)", AmbiguousBindingException.class, - "Found 2 candidate this(), target() or args() variables but only one unbound argument slot"); + "Found 2 candidate this(), target(), or args() variables but only one unbound argument slot"); } @Test void ambiguousArgsBinding() { assertException(getMethod("twoObjects"), "args(x,y)", AmbiguousBindingException.class, - "Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them"); + "Still 2 unbound args at this()/target()/args() binding stage, with no way to determine between them"); } @Test void argsOnePrimitive() { - assertParameterNames(getMethod("onePrimitive"), "args(count)", new String[] {"count"}); + assertParameterNames(getMethod("onePrimitive"), "args(count)", "count"); } @Test @@ -188,37 +187,37 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void thisAndPrimitive() { assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)", - new String[] {"obj", "count"}); + "obj", "count"); } @Test void targetAndPrimitive() { assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)", - new String[] {"obj", "count"}); + "obj", "count"); } @Test void throwingAndPrimitive() { - assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex", - new String[] {"ex", "count"}); + assertParameterNamesExtended(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex", + "ex", "count"); } @Test void allTogetherNow() { - assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex", - new String[] {"thisJoinPoint", "ex", "x", "foo"}); + assertParameterNamesExtended(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex", + "thisJoinPoint", "ex", "x", "foo"); } @Test void referenceBinding() { - assertParameterNames(getMethod("onePrimitive"),"somepc(foo)", new String[] {"foo"}); + assertParameterNames(getMethod("onePrimitive"),"somepc(foo)", "foo"); } @Test void referenceBindingWithAlternateTokenizations() { - assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)", new String[] {"foo"}); - assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )", new String[] {"foo"}); - assertParameterNames(getMethod("onePrimitive"),"somepc( foo)", new String[] {"foo"}); + assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)", "foo"); + assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )", "foo"); + assertParameterNames(getMethod("onePrimitive"),"somepc( foo)", "foo"); } } @@ -230,38 +229,38 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void atThis() { - assertParameterNames(getMethod("oneAnnotation"),"@this(a)", new String[] {"a"}); + assertParameterNames(getMethod("oneAnnotation"),"@this(a)", "a"); } @Test void atTarget() { - assertParameterNames(getMethod("oneAnnotation"),"@target(a)", new String[] {"a"}); + assertParameterNames(getMethod("oneAnnotation"),"@target(a)", "a"); } @Test void atArgs() { - assertParameterNames(getMethod("oneAnnotation"),"@args(a)", new String[] {"a"}); + assertParameterNames(getMethod("oneAnnotation"),"@args(a)", "a"); } @Test void atWithin() { - assertParameterNames(getMethod("oneAnnotation"),"@within(a)", new String[] {"a"}); + assertParameterNames(getMethod("oneAnnotation"),"@within(a)", "a"); } @Test void atWithincode() { - assertParameterNames(getMethod("oneAnnotation"),"@withincode(a)", new String[] {"a"}); + assertParameterNames(getMethod("oneAnnotation"),"@withincode(a)", "a"); } @Test void atAnnotation() { - assertParameterNames(getMethod("oneAnnotation"),"@annotation(a)", new String[] {"a"}); + assertParameterNames(getMethod("oneAnnotation"),"@annotation(a)", "a"); } @Test void ambiguousAnnotationTwoVars() { assertException(getMethod("twoAnnotations"),"@annotation(a) && @this(x)", AmbiguousBindingException.class, - "Found 2 potential annotation variable(s), and 2 potential argument slots"); + "Found 2 potential annotation variable(s) and 2 potential argument slots"); } @Test @@ -272,15 +271,14 @@ class AspectJAdviceParameterNameDiscovererTests { @Test void annotationMedley() { - assertParameterNames(getMethod("annotationMedley"),"@annotation(a) && args(count) && this(foo)", - null, "ex", new String[] {"ex", "foo", "count", "a"}); + assertParameterNamesExtended(getMethod("annotationMedley"),"@annotation(a) && args(count) && this(foo)", + null, "ex", "ex", "foo", "count", "a"); } @Test void annotationBinding() { assertParameterNames(getMethod("pjpAndAnAnnotation"), - "execution(* *(..)) && @annotation(ann)", - new String[] {"thisJoinPoint","ann"}); + "execution(* *(..)) && @annotation(ann)", "thisJoinPoint", "ann"); } } @@ -296,33 +294,23 @@ class AspectJAdviceParameterNameDiscovererTests { throw new AssertionError("Bad test specification, no method '" + name + "' found in test class"); } - private void assertParameterNames(Method method, String pointcut, String[] parameterNames) { - assertParameterNames(method, pointcut, null, null, parameterNames); + private void assertParameterNames(Method method, String pointcut, String... parameterNames) { + assertParameterNamesExtended(method, pointcut, null, null, parameterNames); } - private void assertParameterNames( - Method method, String pointcut, String returning, String throwing, String[] parameterNames) { + private void assertParameterNamesExtended( + Method method, String pointcut, String returning, String throwing, String... parameterNames) { - assertThat(parameterNames.length).as("bad test specification, must have same number of parameter names as method arguments").isEqualTo(method.getParameterCount()); + assertThat(parameterNames) + .as("bad test specification, must have same number of parameter names as method arguments") + .hasSize(method.getParameterCount()); AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut); discoverer.setRaiseExceptions(true); discoverer.setReturningName(returning); discoverer.setThrowingName(throwing); - String[] discoveredNames = discoverer.getParameterNames(method); - String formattedExpectedNames = Arrays.toString(parameterNames); - String formattedActualNames = Arrays.toString(discoveredNames); - - assertThat(discoveredNames.length).as("Expecting " + parameterNames.length + " parameter names in return set '" + - formattedExpectedNames + "', but found " + discoveredNames.length + - " '" + formattedActualNames + "'").isEqualTo(parameterNames.length); - - for (int i = 0; i < discoveredNames.length; i++) { - assertThat(discoveredNames[i]).as("Parameter names must never be null").isNotNull(); - assertThat(discoveredNames[i]).as("Expecting parameter " + i + " to be named '" + - parameterNames[i] + "' but was '" + discoveredNames[i] + "'").isEqualTo(parameterNames[i]); - } + assertThat(discoverer.getParameterNames(method)).isEqualTo(parameterNames); } private void assertException(Method method, String pointcut, Class exceptionType, String message) { diff --git a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java index 835f4a4f95c..4b127181689 100644 --- a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/ArgumentBindingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2023 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. @@ -38,56 +38,55 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; * @author Adrian Colyer * @author Juergen Hoeller * @author Chris Beams + * @author Sam Brannen */ -public class ArgumentBindingTests { +class ArgumentBindingTests { @Test - public void testBindingInPointcutUsedByAdvice() { - TestBean tb = new TestBean(); - AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb); + void bindingInPointcutUsedByAdvice() { + AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean()); proxyFactory.addAspect(NamedPointcutWithArgs.class); ITestBean proxiedTestBean = proxyFactory.getProxy(); - assertThatIllegalArgumentException().isThrownBy(() -> - proxiedTestBean.setName("Supercalifragalisticexpialidocious")); + assertThatIllegalArgumentException() + .isThrownBy(() -> proxiedTestBean.setName("enigma")) + .withMessage("enigma"); } @Test - public void testAnnotationArgumentNameBinding() { - TransactionalBean tb = new TransactionalBean(); - AspectJProxyFactory proxyFactory = new AspectJProxyFactory(tb); + void annotationArgumentNameBinding() { + AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TransactionalBean()); proxyFactory.addAspect(PointcutWithAnnotationArgument.class); ITransactionalBean proxiedTestBean = proxyFactory.getProxy(); - assertThatIllegalStateException().isThrownBy( - proxiedTestBean::doInTransaction); + assertThatIllegalStateException() + .isThrownBy(proxiedTestBean::doInTransaction) + .withMessage("Invoked with @Transactional"); } @Test - public void testParameterNameDiscoverWithReferencePointcut() throws Exception { + void parameterNameDiscoverWithReferencePointcut() throws Exception { AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer("somepc(formal) && set(* *)"); discoverer.setRaiseExceptions(true); - Method methodUsedForParameterTypeDiscovery = - getClass().getMethod("methodWithOneParam", String.class); - String[] pnames = discoverer.getParameterNames(methodUsedForParameterTypeDiscovery); - assertThat(pnames.length).as("one parameter name").isEqualTo(1); - assertThat(pnames[0]).isEqualTo("formal"); + Method method = getClass().getDeclaredMethod("methodWithOneParam", String.class); + assertThat(discoverer.getParameterNames(method)).containsExactly("formal"); } - public void methodWithOneParam(String aParam) { + @SuppressWarnings("unused") + private void methodWithOneParam(String aParam) { } - public interface ITransactionalBean { + interface ITransactionalBean { @Transactional void doInTransaction(); } - public static class TransactionalBean implements ITransactionalBean { + static class TransactionalBean implements ITransactionalBean { @Override @Transactional @@ -95,38 +94,35 @@ public class ArgumentBindingTests { } } -} + /** + * Mimics Spring's @Transactional annotation without actually introducing the dependency. + */ + @Retention(RetentionPolicy.RUNTIME) + @interface Transactional { + } -/** - * Represents Spring's Transactional annotation without actually introducing the dependency - */ -@Retention(RetentionPolicy.RUNTIME) -@interface Transactional { -} + @Aspect + static class PointcutWithAnnotationArgument { + @Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transactional)") + public Object around(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable { + throw new IllegalStateException("Invoked with @Transactional"); + } -@Aspect -class PointcutWithAnnotationArgument { + } + + @Aspect + static class NamedPointcutWithArgs { + + @Pointcut("execution(* *(..)) && args(s,..)") + public void pointcutWithArgs(String s) {} + + @Around("pointcutWithArgs(aString)") + public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable { + throw new IllegalArgumentException(aString); + } - @Around(value = "execution(* org.springframework..*.*(..)) && @annotation(transaction)") - public Object around(ProceedingJoinPoint pjp, Transactional transaction) throws Throwable { - System.out.println("Invoked with transaction " + transaction); - throw new IllegalStateException(); } } - -@Aspect -class NamedPointcutWithArgs { - - @Pointcut("execution(* *(..)) && args(s,..)") - public void pointcutWithArgs(String s) {} - - @Around("pointcutWithArgs(aString)") - public Object doAround(ProceedingJoinPoint pjp, String aString) throws Throwable { - System.out.println("got '" + aString + "' at '" + pjp + "'"); - throw new IllegalArgumentException(aString); - } - -} diff --git a/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java b/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java index d1f9b8ca330..a62b2dc839d 100644 --- a/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java +++ b/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 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. @@ -132,7 +132,7 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM } @Override - public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { + public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener listener : getApplicationListeners(event, type)) { diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index b8d41a36097..a109b6633b2 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -762,7 +762,7 @@ public class ResolvableType implements Serializable { /** * Convenience method that will {@link #getGeneric(int...) get} and - * {@link #resolve() resolve} a specific generic parameters. + * {@link #resolve() resolve} a specific generic parameter. * @param indexes the indexes that refer to the generic parameter * (may be omitted to return the first generic) * @return a resolved {@link Class} or {@code null} diff --git a/spring-core/src/main/java/org/springframework/core/log/LogMessage.java b/spring-core/src/main/java/org/springframework/core/log/LogMessage.java index c661f4a43e1..168cc3969e2 100644 --- a/spring-core/src/main/java/org/springframework/core/log/LogMessage.java +++ b/spring-core/src/main/java/org/springframework/core/log/LogMessage.java @@ -22,10 +22,10 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * A simple log message type for use with Commons Logging, allowing - * for convenient lazy resolution of a given {@link Supplier} instance - * (typically bound to a Java 8 lambda expression) or a printf-style - * format string ({@link String#format}) in its {@link #toString()}. + * A simple log message type for use with Commons Logging, allowing for convenient + * lazy resolution of a given {@link Supplier} instance (typically bound to a lambda + * expression) or a printf-style format string ({@link String#format}) in its + * {@link #toString()}. * * @author Juergen Hoeller * @author Sebastien Deleuze @@ -78,7 +78,7 @@ public abstract class LogMessage implements CharSequence { /** * Build a lazily resolving message from the given supplier. - * @param supplier the supplier (typically bound to a Java 8 lambda expression) + * @param supplier the supplier (typically bound to a lambda expression) * @see #toString() */ public static LogMessage of(Supplier supplier) { @@ -134,8 +134,12 @@ public abstract class LogMessage implements CharSequence { /** * Build a lazily formatted message from the given format string and varargs. + *

This varargs {@code format()} variant may be costly. You should therefore + * use the individual argument variants whenever possible; + * {@link #format(String, Object)}, {@link #format(String, Object, Object)}, etc. * @param format the format string (following {@link String#format} rules) - * @param args the varargs array (can be {@code null}, costly, prefer individual arguments) + * @param args the varargs array (can be {@code null} and can contain {@code null} + * elements) * @see String#format(String, Object...) */ public static LogMessage format(String format, @Nullable Object... args) {