diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index fe9fbd44ed0..4cabec4e5cb 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -120,7 +120,13 @@ class ConfigurationClassBeanDefinitionReader { public void loadBeanDefinitions(Set configurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); for (ConfigurationClass configClass : configurationModel) { - loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); + try { + loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); + } + catch (Exception ex) { + throw new IllegalStateException("Failed to load bean definitions for configuration class '" + + configClass.getMetadata().getClassName() + "'", ex); + } } } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java index 0e0f877b735..66d9d40bb67 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java @@ -422,23 +422,36 @@ class ConfigurationClassPostProcessorTests { beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class)); beanFactory.setAllowBeanDefinitionOverriding(false); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); - assertThatExceptionOfType(BeanDefinitionStoreException.class) + + assertThatIllegalStateException() .isThrownBy(() -> pp.postProcessBeanFactory(beanFactory)) - .withMessageContaining("bar") - .withMessageContaining("SingletonBeanConfig") - .withMessageContaining(TestBean.class.getName()); + .withMessage("Failed to load bean definitions for configuration class '%s'", SingletonBeanConfig.class.getName()) + .havingCause() + .isInstanceOf(BeanDefinitionStoreException.class) + .withMessageContainingAll( + "bar", + "SingletonBeanConfig", + TestBean.class.getName() + ); } @Test // gh-25430 void detectAliasOverride() { + Class configClass = SecondConfiguration.class; AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory(); beanFactory.setAllowBeanDefinitionOverriding(false); - context.register(FirstConfiguration.class, SecondConfiguration.class); + context.register(FirstConfiguration.class, configClass); + assertThatIllegalStateException().isThrownBy(context::refresh) - .withMessageContaining("alias 'taskExecutor'") - .withMessageContaining("name 'applicationTaskExecutor'") - .withMessageContaining("bean definition 'taskExecutor'"); + .withMessage("Failed to load bean definitions for configuration class '%s'", configClass.getName()) + .havingCause() + .isExactlyInstanceOf(IllegalStateException.class) + .withMessageContainingAll( + "alias 'taskExecutor'", + "name 'applicationTaskExecutor'", + "bean definition 'taskExecutor'" + ); context.close(); } @@ -1052,7 +1065,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testSelfReferenceExclusionForFactoryMethodOnSameBean() { + void selfReferenceExclusionForFactoryMethodOnSameBean() { AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(beanFactory); beanFactory.addBeanPostProcessor(bpp); @@ -1066,7 +1079,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testConfigWithDefaultMethods() { + void configWithDefaultMethods() { AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(beanFactory); beanFactory.addBeanPostProcessor(bpp); @@ -1080,7 +1093,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testConfigWithDefaultMethodsUsingAsm() { + void configWithDefaultMethodsUsingAsm() { AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(beanFactory); beanFactory.addBeanPostProcessor(bpp); @@ -1094,7 +1107,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testConfigWithFailingInit() { // gh-23343 + void configWithFailingInit() { // gh-23343 AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(beanFactory); beanFactory.addBeanPostProcessor(bpp); @@ -1108,7 +1121,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testCircularDependency() { + void circularDependency() { AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(beanFactory); beanFactory.addBeanPostProcessor(bpp); @@ -1122,42 +1135,42 @@ class ConfigurationClassPostProcessorTests { } @Test - void testCircularDependencyWithApplicationContext() { + void circularDependencyWithApplicationContext() { assertThatExceptionOfType(BeanCreationException.class) .isThrownBy(() -> new AnnotationConfigApplicationContext(A.class, AStrich.class)) .withMessageContaining("Circular reference"); } @Test - void testPrototypeArgumentThroughBeanMethodCall() { + void prototypeArgumentThroughBeanMethodCall() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithPrototype.class); ctx.getBean(FooFactory.class).createFoo(new BarArgument()); ctx.close(); } @Test - void testSingletonArgumentThroughBeanMethodCall() { + void singletonArgumentThroughBeanMethodCall() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithSingleton.class); ctx.getBean(FooFactory.class).createFoo(new BarArgument()); ctx.close(); } @Test - void testNullArgumentThroughBeanMethodCall() { + void nullArgumentThroughBeanMethodCall() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(BeanArgumentConfigWithNull.class); ctx.getBean("aFoo"); ctx.close(); } @Test - void testInjectionPointMatchForNarrowTargetReturnType() { + void injectionPointMatchForNarrowTargetReturnType() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(FooBarConfiguration.class); assertThat(ctx.getBean(FooImpl.class).bar).isSameAs(ctx.getBean(BarImpl.class)); ctx.close(); } @Test - void testVarargOnBeanMethod() { + void varargOnBeanMethod() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(VarargConfiguration.class, TestBean.class); VarargConfiguration bean = ctx.getBean(VarargConfiguration.class); assertThat(bean.testBeans).isNotNull(); @@ -1167,7 +1180,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testEmptyVarargOnBeanMethod() { + void emptyVarargOnBeanMethod() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(VarargConfiguration.class); VarargConfiguration bean = ctx.getBean(VarargConfiguration.class); assertThat(bean.testBeans).isNotNull(); @@ -1176,7 +1189,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testCollectionArgumentOnBeanMethod() { + void collectionArgumentOnBeanMethod() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionArgumentConfiguration.class, TestBean.class); CollectionArgumentConfiguration bean = ctx.getBean(CollectionArgumentConfiguration.class); assertThat(bean.testBeans).containsExactly(ctx.getBean(TestBean.class)); @@ -1184,7 +1197,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testEmptyCollectionArgumentOnBeanMethod() { + void emptyCollectionArgumentOnBeanMethod() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionArgumentConfiguration.class); CollectionArgumentConfiguration bean = ctx.getBean(CollectionArgumentConfiguration.class); assertThat(bean.testBeans).isEmpty(); @@ -1192,7 +1205,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testMapArgumentOnBeanMethod() { + void mapArgumentOnBeanMethod() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(MapArgumentConfiguration.class, DummyRunnable.class); MapArgumentConfiguration bean = ctx.getBean(MapArgumentConfiguration.class); assertThat(bean.testBeans).hasSize(1).containsValue(ctx.getBean(Runnable.class)); @@ -1200,7 +1213,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testEmptyMapArgumentOnBeanMethod() { + void emptyMapArgumentOnBeanMethod() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(MapArgumentConfiguration.class); MapArgumentConfiguration bean = ctx.getBean(MapArgumentConfiguration.class); assertThat(bean.testBeans).isEmpty(); @@ -1208,7 +1221,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testCollectionInjectionFromSameConfigurationClass() { + void collectionInjectionFromSameConfigurationClass() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionInjectionConfiguration.class); CollectionInjectionConfiguration bean = ctx.getBean(CollectionInjectionConfiguration.class); assertThat(bean.testBeans).containsExactly(ctx.getBean(TestBean.class)); @@ -1216,7 +1229,7 @@ class ConfigurationClassPostProcessorTests { } @Test - void testMapInjectionFromSameConfigurationClass() { + void mapInjectionFromSameConfigurationClass() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(MapInjectionConfiguration.class); MapInjectionConfiguration bean = ctx.getBean(MapInjectionConfiguration.class); assertThat(bean.testBeans).containsOnly(Map.entry("testBean", ctx.getBean(Runnable.class))); @@ -1224,20 +1237,23 @@ class ConfigurationClassPostProcessorTests { } @Test - void testBeanLookupFromSameConfigurationClass() { + void beanLookupFromSameConfigurationClass() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(BeanLookupConfiguration.class); assertThat(ctx.getBean(BeanLookupConfiguration.class).getTestBean()).isSameAs(ctx.getBean(TestBean.class)); ctx.close(); } @Test - void testNameClashBetweenConfigurationClassAndBean() { - assertThatExceptionOfType(BeanDefinitionStoreException.class) - .isThrownBy(() -> new AnnotationConfigApplicationContext(MyTestBean.class).getBean("myTestBean", TestBean.class)); + void nameClashBetweenConfigurationClassAndBean() { + assertThatIllegalStateException() + .isThrownBy(() -> new AnnotationConfigApplicationContext(MyTestBean.class)) + .withMessage("Failed to load bean definitions for configuration class '%s'", MyTestBean.class.getName()) + .havingCause() + .isInstanceOf(BeanDefinitionStoreException.class); } @Test - void testBeanDefinitionRegistryPostProcessorConfig() { + void beanDefinitionRegistryPostProcessorConfig() { ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(BeanDefinitionRegistryPostProcessorConfig.class); assertThat(ctx.getBean("myTestBean")).isInstanceOf(TestBean.class); ctx.close(); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java index 2ded0c1b98d..60908e38107 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java @@ -60,6 +60,7 @@ import org.springframework.context.support.GenericApplicationContext; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** * Miscellaneous system tests covering {@link Bean} naming, aliases, scoping and @@ -219,8 +220,12 @@ class ConfigurationClassProcessingTests { @Test // gh-33330 void configurationWithMethodNameMismatch() { - assertThatExceptionOfType(BeanDefinitionOverrideException.class) - .isThrownBy(() -> initBeanFactory(false, ConfigWithMethodNameMismatch.class)); + Class configClass = ConfigWithMethodNameMismatch.class; + assertThatIllegalStateException() + .isThrownBy(() -> initBeanFactory(false, configClass)) + .withMessage("Failed to load bean definitions for configuration class '%s'", configClass.getName()) + .havingCause() + .isInstanceOf(BeanDefinitionOverrideException.class); } @Test // gh-33920