Skip to content

Commit 04313f0

Browse files
committed
Improve documentation for FullyQualifiedConfigurationBeanNameGenerator
This commit documents FullyQualifiedConfigurationBeanNameGenerator in related Javadoc and in the reference manual. See gh-33448 Closes gh-36455
1 parent e634ced commit 04313f0

File tree

11 files changed

+106
-45
lines changed

11 files changed

+106
-45
lines changed

framework-docs/modules/ROOT/pages/core/beans/classpath-scanning.adoc

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -556,18 +556,11 @@ Kotlin::
556556
======
557557

558558
If you do not want to rely on the default bean-naming strategy, you can provide a custom
559-
bean-naming strategy. First, implement the
560-
{spring-framework-api}/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`]
559+
bean-naming strategy. First, implement either the
560+
{spring-framework-api}/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`] or
561+
{spring-framework-api}/context/annotation/ConfigurationBeanNameGenerator.html[`ConfigurationBeanNameGenerator`]
561562
interface, and be sure to include a default no-arg constructor. Then, provide the fully
562-
qualified class name when configuring the scanner, as the following example annotation
563-
and bean definition show.
564-
565-
TIP: If you run into naming conflicts due to multiple autodetected components having the
566-
same non-qualified class name (i.e., classes with identical names but residing in
567-
different packages), you may need to configure a `BeanNameGenerator` that defaults to the
568-
fully qualified class name for the generated bean name. The
569-
`FullyQualifiedAnnotationBeanNameGenerator` located in package
570-
`org.springframework.context.annotation` can be used for such purposes.
563+
qualified class name when configuring the scanner, as the following examples show.
571564

572565
[tabs]
573566
======
@@ -602,6 +595,27 @@ Kotlin::
602595
</beans>
603596
----
604597

598+
[TIP]
599+
====
600+
If you run into naming conflicts due to multiple autodetected components having the same
601+
non-qualified class name (for example, classes with identical names but residing in
602+
different packages), you can configure a `BeanNameGenerator` that defaults to the
603+
fully-qualified class name for the generated bean name. The
604+
`FullyQualifiedAnnotationBeanNameGenerator` can be used for such purposes.
605+
606+
As of Spring Framework 7.0, if you encounter naming conflicts among `@Bean` methods in
607+
`@Configuration` classes, you can alternatively configure a
608+
`ConfigurationBeanNameGenerator` that generates unique bean names for `@Bean` methods.
609+
The `FullyQualifiedConfigurationBeanNameGenerator` can be used to generate
610+
fully-qualified default bean names for `@Bean` methods without an explicit `name`
611+
attribute — for example, `com.example.MyConfig.myBean` for an `@Bean` method named
612+
`myBean()` declared in `@Configuration` class `com.example.MyConfig`.
613+
614+
The `FullyQualifiedAnnotationBeanNameGenerator` and
615+
`FullyQualifiedConfigurationBeanNameGenerator` both reside in the
616+
`org.springframework.context.annotation` package.
617+
====
618+
605619
As a general rule, consider specifying the name with the annotation whenever other
606620
components may be making explicit references to it. On the other hand, the
607621
auto-generated names are adequate whenever the container is responsible for wiring.

framework-docs/modules/ROOT/pages/core/beans/java/bean-annotation.adoc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
`@Bean` is a method-level annotation and a direct analog of the XML `<bean/>` element.
55
The annotation supports some of the attributes offered by `<bean/>`, such as:
66

7+
* xref:core/beans/definition.adoc#beans-beanname[name]
78
* xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-initializingbean[init-method]
89
* xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-disposablebean[destroy-method]
910
* xref:core/beans/dependencies/factory-autowire.adoc[autowiring]
10-
* `name`.
1111

1212
You can use the `@Bean` annotation in a `@Configuration`-annotated or in a
1313
`@Component`-annotated class.
@@ -17,9 +17,10 @@ You can use the `@Bean` annotation in a `@Configuration`-annotated or in a
1717
== Declaring a Bean
1818

1919
To declare a bean, you can annotate a method with the `@Bean` annotation. You use this
20-
method to register a bean definition within an `ApplicationContext` of the type
21-
specified as the method's return value. By default, the bean name is the same as
22-
the method name. The following example shows a `@Bean` method declaration:
20+
method to register a bean definition within an `ApplicationContext` of the type specified
21+
by the method's return type. By default, the bean name is the same as the method name
22+
(unless a different xref:#beans-java-customizing-bean-naming[bean name generator] is
23+
configured). The following example shows a `@Bean` method declaration:
2324

2425
[tabs]
2526
======
@@ -126,7 +127,7 @@ Kotlin::
126127
----
127128
======
128129

129-
However, this limits the visibility for advance type prediction to the specified
130+
However, this limits the visibility for advanced type prediction to the specified
130131
interface type (`TransferService`). Then, with the full type (`TransferServiceImpl`)
131132
known to the container only once the affected singleton bean has been instantiated.
132133
Non-lazy singleton beans get instantiated according to their declaration order,
@@ -473,8 +474,15 @@ Kotlin::
473474
== Customizing Bean Naming
474475

475476
By default, configuration classes use a `@Bean` method's name as the name of the
476-
resulting bean. This functionality can be overridden, however, with the `name` attribute,
477-
as the following example shows:
477+
resulting bean. However, as of Spring Framework 7.0, you can change this default strategy
478+
by configuring a custom
479+
{spring-framework-api}/context/annotation/ConfigurationBeanNameGenerator.html[`ConfigurationBeanNameGenerator`]
480+
when bootstrapping the context or configuring component scanning. For example,
481+
{spring-framework-api}/context/annotation/FullyQualifiedConfigurationBeanNameGenerator.html[`FullyQualifiedConfigurationBeanNameGenerator`]
482+
can be used to generate fully-qualified default bean names for `@Bean` methods without an
483+
explicit `name` attribute. For individual `@Bean` methods, the default or
484+
generator-derived name can be overridden with the `name` attribute, as the following
485+
example shows:
478486

479487
[tabs]
480488
======
@@ -505,6 +513,7 @@ Kotlin::
505513
----
506514
======
507515

516+
NOTE: `@Bean("myThing")` is equivalent to `@Bean(name = "myThing")`.
508517

509518
[[beans-java-bean-aliasing]]
510519
== Bean Aliasing

spring-beans/src/main/java/org/springframework/beans/factory/support/BeanNameGenerator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*
2424
* @author Juergen Hoeller
2525
* @since 2.0.3
26+
* @see org.springframework.context.annotation.ConfigurationBeanNameGenerator
2627
*/
2728
public interface BeanNameGenerator {
2829

spring-context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ public void setEnvironment(Environment environment) {
109109

110110
/**
111111
* Set the {@code BeanNameGenerator} to use for detected bean classes.
112-
* <p>The default is a {@link AnnotationBeanNameGenerator}.
112+
* <p>The default is an {@link AnnotationBeanNameGenerator}.
113+
* @see FullyQualifiedAnnotationBeanNameGenerator
114+
* @see FullyQualifiedConfigurationBeanNameGenerator
113115
*/
114116
public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) {
115117
this.beanNameGenerator =

spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,20 @@ public void setEnvironment(ConfigurableEnvironment environment) {
118118

119119
/**
120120
* Provide a custom {@link BeanNameGenerator} for use with {@link AnnotatedBeanDefinitionReader}
121-
* and/or {@link ClassPathBeanDefinitionScanner}, if any.
122-
* <p>Default is {@link AnnotationBeanNameGenerator}.
121+
* and/or {@link ClassPathBeanDefinitionScanner}.
122+
* <p>Default is {@code AnnotationBeanNameGenerator}.
123+
* <p>When processing {@link Configuration @Configuration} classes, a
124+
* {@link ConfigurationBeanNameGenerator} (such as
125+
* {@link FullyQualifiedConfigurationBeanNameGenerator}) also determines the
126+
* default names for {@link Bean @Bean} methods without an explicit {@code name}
127+
* attribute.
123128
* <p>Any call to this method must occur prior to calls to {@link #register(Class...)}
124129
* and/or {@link #scan(String...)}.
125130
* @see AnnotatedBeanDefinitionReader#setBeanNameGenerator
126131
* @see ClassPathBeanDefinitionScanner#setBeanNameGenerator
127132
* @see AnnotationBeanNameGenerator
128133
* @see FullyQualifiedAnnotationBeanNameGenerator
134+
* @see FullyQualifiedConfigurationBeanNameGenerator
129135
*/
130136
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
131137
this.reader.setBeanNameGenerator(beanNameGenerator);

spring-context/src/main/java/org/springframework/context/annotation/Bean.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@
4545
*
4646
* <p>While a {@link #name} attribute is available, the default strategy for
4747
* determining the name of a bean is to use the name of the {@code @Bean} method.
48-
* This is convenient and intuitive, but if explicit naming is desired, the
49-
* {@code name} attribute (or its alias {@code value}) may be used. Also note
50-
* that {@code name} accepts an array of Strings, allowing for multiple names
51-
* (i.e. a primary bean name plus one or more aliases) for a single bean.
48+
* This default can be overridden by configuring a {@link ConfigurationBeanNameGenerator}
49+
* &mdash; for example, {@link FullyQualifiedConfigurationBeanNameGenerator} for
50+
* fully-qualified names. If explicit naming is desired for an individual bean, the
51+
* {@code name} attribute (or its alias {@link #value}) may be used. Also note that
52+
* {@code name} accepts an array of Strings, allowing for multiple names (i.e., a
53+
* primary bean name plus one or more aliases) for a single bean.
5254
*
5355
* <pre class="code">
5456
* &#064;Bean({"b1", "b2"}) // bean available as 'b1' and 'b2', but not 'myBean'
@@ -237,6 +239,9 @@
237239
* @see org.springframework.stereotype.Component
238240
* @see org.springframework.beans.factory.annotation.Autowired
239241
* @see org.springframework.beans.factory.annotation.Value
242+
* @see FullyQualifiedConfigurationBeanNameGenerator
243+
* @see AnnotationConfigApplicationContext#setBeanNameGenerator
244+
* @see ComponentScan#nameGenerator()
240245
*/
241246
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
242247
@Retention(RetentionPolicy.RUNTIME)
@@ -255,10 +260,11 @@
255260

256261
/**
257262
* The name of this bean, or if several names, a primary bean name plus aliases.
258-
* <p>If left unspecified, the name of the bean is the name of the annotated method.
259-
* If specified, the method name is ignored.
263+
* <p>See the "Bean Names" section in the {@linkplain Bean class-level documentation}
264+
* for details on how the bean name is determined if this attribute is left
265+
* unspecified.
260266
* <p>The bean name and aliases may also be configured via the {@link #value}
261-
* attribute if no other attributes are declared.
267+
* attribute.
262268
* @see #value
263269
*/
264270
@AliasFor("value")

spring-context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@
4343
* or {@code ApplicationContext}).
4444
*
4545
* <p>Candidate classes are detected through configurable type filters. The
46-
* default filters include classes that are annotated with Spring's
47-
* {@link org.springframework.stereotype.Component @Component},
46+
* default filters include classes that are annotated or meta-annotated with Spring's
47+
* {@link org.springframework.stereotype.Component @Component} annotation, such as the
4848
* {@link org.springframework.stereotype.Repository @Repository},
49-
* {@link org.springframework.stereotype.Service @Service}, or
50-
* {@link org.springframework.stereotype.Controller @Controller} stereotype.
49+
* {@link org.springframework.stereotype.Service @Service}, and
50+
* {@link org.springframework.stereotype.Controller @Controller} stereotypes.
5151
*
5252
* <p>Also supports JSR-330's {@link jakarta.inject.Named} annotations, if available.
5353
*
@@ -204,8 +204,11 @@ public void setAutowireCandidatePatterns(String @Nullable ... autowireCandidateP
204204
}
205205

206206
/**
207-
* Set the BeanNameGenerator to use for detected bean classes.
208-
* <p>Default is a {@link AnnotationBeanNameGenerator}.
207+
* Set the {@link BeanNameGenerator} to use for detected bean classes.
208+
* <p>Default is an {@code AnnotationBeanNameGenerator}.
209+
* @see AnnotationBeanNameGenerator
210+
* @see FullyQualifiedAnnotationBeanNameGenerator
211+
* @see FullyQualifiedConfigurationBeanNameGenerator
209212
*/
210213
public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) {
211214
this.beanNameGenerator =

spring-context/src/main/java/org/springframework/context/annotation/ComponentScan.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,18 @@
109109
/**
110110
* The {@link BeanNameGenerator} class to be used for naming detected components
111111
* within the Spring container.
112-
* <p>The default value of the {@link BeanNameGenerator} interface itself indicates
112+
* <p>The default value of the {@code BeanNameGenerator} interface itself indicates
113113
* that the scanner used to process this {@code @ComponentScan} annotation should
114114
* use its inherited bean name generator, for example, the default
115115
* {@link AnnotationBeanNameGenerator} or any custom instance supplied to the
116-
* application context at bootstrap time.
116+
* application context at bootstrap time. If a {@link ConfigurationBeanNameGenerator}
117+
* is used (such as {@link FullyQualifiedConfigurationBeanNameGenerator}), it
118+
* also affects the default names for {@link Bean @Bean} methods in
119+
* {@link Configuration @Configuration} classes.
117120
* @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator)
118121
* @see AnnotationBeanNameGenerator
119122
* @see FullyQualifiedAnnotationBeanNameGenerator
123+
* @see FullyQualifiedConfigurationBeanNameGenerator
120124
*/
121125
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
122126

spring-context/src/main/java/org/springframework/context/annotation/Configuration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@
437437
* <p>Alias for {@link Component#value}.
438438
* @return the explicit component name, if any (or empty String otherwise)
439439
* @see AnnotationBeanNameGenerator
440+
* @see FullyQualifiedAnnotationBeanNameGenerator
441+
* @see FullyQualifiedConfigurationBeanNameGenerator
440442
*/
441443
@AliasFor(annotation = Component.class)
442444
String value() default "";

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,19 +242,25 @@ public void setMetadataReaderFactory(MetadataReaderFactory metadataReaderFactory
242242

243243
/**
244244
* Set the {@link BeanNameGenerator} to be used when triggering component scanning
245-
* from {@link Configuration} classes and when registering {@link Import}'ed
246-
* configuration classes. The default is a standard {@link AnnotationBeanNameGenerator}
247-
* for scanned components (compatible with the default in {@link ClassPathBeanDefinitionScanner})
245+
* from {@link Configuration @Configuration} classes and when registering
246+
* {@link Import @Import}'ed configuration classes.
247+
* <p>The default is a standard {@link AnnotationBeanNameGenerator} for scanned
248+
* components (compatible with the default in {@link ClassPathBeanDefinitionScanner})
248249
* and a variant thereof for imported configuration classes (using unique fully-qualified
249250
* class names instead of standard component overriding).
250-
* <p>Note that this strategy does <em>not</em> apply to {@link Bean} methods.
251+
* <p>If the supplied bean name generator is a {@link ConfigurationBeanNameGenerator}
252+
* (such as {@link FullyQualifiedConfigurationBeanNameGenerator}), it also affects the
253+
* default names for {@link Bean @Bean} methods in configuration classes.
251254
* <p>This setter is typically only appropriate when configuring the post-processor as a
252255
* standalone bean definition in XML, for example, not using the dedicated {@code AnnotationConfig*}
253256
* application contexts or the {@code <context:annotation-config>} element. Any bean name
254257
* generator specified against the application context will take precedence over any set here.
255258
* @since 3.1.1
256259
* @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator)
257260
* @see AnnotationConfigUtils#CONFIGURATION_BEAN_NAME_GENERATOR
261+
* @see AnnotationBeanNameGenerator
262+
* @see FullyQualifiedAnnotationBeanNameGenerator
263+
* @see FullyQualifiedConfigurationBeanNameGenerator
258264
*/
259265
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
260266
Assert.notNull(beanNameGenerator, "BeanNameGenerator must not be null");

0 commit comments

Comments
 (0)