From 43ff6d9711540a8ca048867a27fb42db4a232c70 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 12 Dec 2024 22:16:24 +0100 Subject: [PATCH] Deprecate use of several bean factory methods for the same bean See gh-31073 --- .../context/annotation/Configuration.java | 5 +++- ...onfigurationClassBeanDefinitionReader.java | 27 ++++++++++--------- .../ConfigurationClassProcessingTests.java | 2 +- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java b/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java index 96314a730230..b279917f6365 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/Configuration.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. @@ -471,7 +471,10 @@ * Switch this flag to {@code false} in order to allow for method overloading * according to those semantics, accepting the risk for accidental overlaps. * @since 6.0 + * @deprecated as of 7.0, always relying on {@code @Bean} unique methods, + * just possibly with {@code Optional}/{@code ObjectProvider} arguments */ + @Deprecated(since = "7.0") boolean enforceUniqueMethods() default true; } 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 8385b9ef34e8..0634bd6edcaf 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 @@ -292,6 +292,7 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { this.registry.registerBeanDefinition(beanName, beanDefToRegister); } + @SuppressWarnings("NullAway") protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) { if (!this.registry.containsBeanDefinition(beanName)) { return false; @@ -302,21 +303,23 @@ protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String // If the bean method is an overloaded case on the same configuration class, // preserve the existing bean definition and mark it as overloaded. if (existingBeanDef instanceof ConfigurationClassBeanDefinition ccbd) { - if (ccbd.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) { - if (ccbd.getFactoryMethodMetadata().getMethodName().equals(beanMethod.getMetadata().getMethodName())) { - ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName()); - } - else if (!this.registry.isBeanDefinitionOverridable(beanName)) { - throw new BeanDefinitionOverrideException(beanName, - new ConfigurationClassBeanDefinition(configClass, beanMethod.getMetadata(), beanName), - existingBeanDef, - "@Bean method override with same bean name but different method name: " + existingBeanDef); - } + if (!ccbd.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) { + return false; + } + if (ccbd.getFactoryMethodMetadata().getMethodName().equals(beanMethod.getMetadata().getMethodName())) { + ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName()); return true; } - else { - return false; + Map attributes = + configClass.getMetadata().getAnnotationAttributes(Configuration.class.getName()); + if ((attributes != null && (Boolean) attributes.get("enforceUniqueMethods")) || + !this.registry.isBeanDefinitionOverridable(beanName)) { + throw new BeanDefinitionOverrideException(beanName, + new ConfigurationClassBeanDefinition(configClass, beanMethod.getMetadata(), beanName), + existingBeanDef, + "@Bean method override with same bean name but different method name: " + existingBeanDef); } + return true; } // A bean definition resulting from a component scan can be silently overridden 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 2e2ef9173261..aab9898618e9 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 @@ -542,7 +542,7 @@ public TestBean bar() { } - @Configuration + @Configuration(enforceUniqueMethods = false) static class ConfigWithMethodNameMismatch { @Bean(name = "foo") public TestBean foo1() {