diff --git a/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJEnableCachingIsolatedTests.java b/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJEnableCachingIsolatedTests.java index df8e1d3588a..bbc972dbc07 100644 --- a/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJEnableCachingIsolatedTests.java +++ b/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJEnableCachingIsolatedTests.java @@ -95,7 +95,9 @@ class AspectJEnableCachingIsolatedTests { } catch (NoUniqueBeanDefinitionException ex) { assertThat(ex.getMessage()).contains( - "no CacheResolver specified and expected a single CacheManager bean, but found 2: [cm1,cm2]"); + "no CacheResolver specified and expected single matching CacheManager but found 2: cm1,cm2"); + assertThat(ex.getNumberOfBeansFound()).isEqualTo(2); + assertThat(ex.getBeanNamesFound()).containsExactly("cm1", "cm2"); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/NoUniqueBeanDefinitionException.java b/spring-beans/src/main/java/org/springframework/beans/factory/NoUniqueBeanDefinitionException.java index 9e30f2f72c5..c2a6070c9d3 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/NoUniqueBeanDefinitionException.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/NoUniqueBeanDefinitionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -29,6 +29,7 @@ import org.springframework.util.StringUtils; * multiple matching candidates have been found when only one matching bean was expected. * * @author Juergen Hoeller + * @author Stephane Nicoll * @since 3.2.1 * @see BeanFactory#getBean(Class) */ @@ -41,6 +42,19 @@ public class NoUniqueBeanDefinitionException extends NoSuchBeanDefinitionExcepti private final Collection beanNamesFound; + /** + * Create a new {@code NoUniqueBeanDefinitionException}. + * @param type required type of the non-unique bean + * @param beanNamesFound the names of all matching beans (as a Collection) + * @param message detailed message describing the problem + * @since 6.2 + */ + public NoUniqueBeanDefinitionException(Class type, Collection beanNamesFound, String message) { + super(type, message); + this.numberOfBeansFound = beanNamesFound.size(); + this.beanNamesFound = new ArrayList<>(beanNamesFound); + } + /** * Create a new {@code NoUniqueBeanDefinitionException}. * @param type required type of the non-unique bean @@ -59,10 +73,8 @@ public class NoUniqueBeanDefinitionException extends NoSuchBeanDefinitionExcepti * @param beanNamesFound the names of all matching beans (as a Collection) */ public NoUniqueBeanDefinitionException(Class type, Collection beanNamesFound) { - super(type, "expected single matching bean but found " + beanNamesFound.size() + ": " + + this(type, beanNamesFound, "expected single matching bean but found " + beanNamesFound.size() + ": " + StringUtils.collectionToCommaDelimitedString(beanNamesFound)); - this.numberOfBeansFound = beanNamesFound.size(); - this.beanNamesFound = new ArrayList<>(beanNamesFound); } /** diff --git a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java index ff01be10870..e9594894962 100644 --- a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java +++ b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java @@ -270,13 +270,22 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker setCacheManager(this.beanFactory.getBean(CacheManager.class)); } catch (NoUniqueBeanDefinitionException ex) { - StringBuilder message = new StringBuilder("no CacheResolver specified and expected a single CacheManager bean, but found "); - message.append(ex.getNumberOfBeansFound()); - if (ex.getBeanNamesFound() != null) { - message.append(": [").append(StringUtils.collectionToCommaDelimitedString(ex.getBeanNamesFound())).append("]"); + int numberOfBeansFound = ex.getNumberOfBeansFound(); + Collection beanNamesFound = ex.getBeanNamesFound(); + + StringBuilder message = new StringBuilder("no CacheResolver specified and expected single matching CacheManager but found "); + message.append(numberOfBeansFound); + if (beanNamesFound != null) { + message.append(": ").append(StringUtils.collectionToCommaDelimitedString(beanNamesFound)); + } + String exceptionMessage = message.toString(); + + if (beanNamesFound != null) { + throw new NoUniqueBeanDefinitionException(CacheManager.class, beanNamesFound, exceptionMessage); + } + else { + throw new NoUniqueBeanDefinitionException(CacheManager.class, numberOfBeansFound, exceptionMessage); } - message.append(" - mark one as primary or declare a specific CacheManager to use."); - throw new NoUniqueBeanDefinitionException(CacheManager.class, ex.getNumberOfBeansFound(), message.toString()); } catch (NoSuchBeanDefinitionException ex) { throw new NoSuchBeanDefinitionException(CacheManager.class, "no CacheResolver specified - " diff --git a/spring-context/src/test/java/org/springframework/cache/config/EnableCachingTests.java b/spring-context/src/test/java/org/springframework/cache/config/EnableCachingTests.java index 8762ec2d41a..923cf62ac9f 100644 --- a/spring-context/src/test/java/org/springframework/cache/config/EnableCachingTests.java +++ b/spring-context/src/test/java/org/springframework/cache/config/EnableCachingTests.java @@ -92,9 +92,12 @@ class EnableCachingTests extends AbstractCacheAnnotationTests { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(MultiCacheManagerConfig.class); assertThatThrownBy(ctx::refresh) - .isInstanceOf(NoUniqueBeanDefinitionException.class) - .hasMessageContaining("no CacheResolver specified and expected a single CacheManager bean, but found 2: [cm1,cm2]") - .hasNoCause(); + .isInstanceOfSatisfying(NoUniqueBeanDefinitionException.class, ex -> { + assertThat(ex.getMessage()).contains( + "no CacheResolver specified and expected single matching CacheManager but found 2: cm1,cm2"); + assertThat(ex.getNumberOfBeansFound()).isEqualTo(2); + assertThat(ex.getBeanNamesFound()).containsExactly("cm1", "cm2"); + }).hasNoCause(); } @Test