Prevent empty declaration of @⁠ConcurrencyLimit

As a follow-up to gh-35461 and a comment left on the Spring Blog, we
have decided to prevent empty declarations of @⁠ConcurrencyLimit,
thereby requiring users to explicitly declare the value for the limit.

Closes gh-35523
This commit is contained in:
Sam Brannen
2025-09-22 18:18:53 +02:00
parent 8b254ad25e
commit 5ac3c40689
3 changed files with 110 additions and 30 deletions
@@ -64,25 +64,30 @@ public @interface ConcurrencyLimit {
* @see #limitString()
*/
@AliasFor("limit")
int value() default 1;
int value() default Integer.MIN_VALUE;
/**
* The applicable concurrency limit: 1 by default,
* effectively locking the target instance for each method invocation.
* <p>Specify a limit higher than 1 for pool-like throttling, constraining
* The concurrency limit.
* <p>Specify {@code 1} to effectively lock the target instance for each method
* invocation.
* <p>Specify a limit greater than {@code 1} for pool-like throttling, constraining
* the number of concurrent invocations similar to the upper bound of a pool.
* <p>Specify {@code -1} for unbounded concurrency.
* @see #value()
* @see #limitString()
* @see org.springframework.util.ConcurrencyThrottleSupport#UNBOUNDED_CONCURRENCY
*/
@AliasFor("value")
int limit() default 1;
int limit() default Integer.MIN_VALUE;
/**
* The concurrency limit, as a configurable String.
* <p>A non-empty value specified here overrides the {@link #limit()} (or
* {@link #value()}) attribute.
* <p>A non-empty value specified here overrides the {@link #limit()} and
* {@link #value()} attributes.
* <p>This supports Spring-style "${...}" placeholders as well as SpEL expressions.
* <p>See the Javadoc for {@link #limit()} for details on supported values.
* @see #limit()
* @see org.springframework.util.ConcurrencyThrottleSupport#UNBOUNDED_CONCURRENCY
*/
String limitString() default "";
@@ -108,6 +108,9 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
if (interceptor == null) {
Assert.state(annotation != null, "No @ConcurrencyLimit annotation found");
int concurrencyLimit = parseInt(annotation.limit(), annotation.limitString());
if (concurrencyLimit < -1) {
throw new IllegalStateException(annotation + " must be configured with a valid limit");
}
interceptor = new ConcurrencyThrottleInterceptor(concurrencyLimit);
if (!perMethod) {
cache.classInterceptor = interceptor;