Skip to content

Commit 8818176

Browse files
committed
Scope annotation in class hierarchies vs XML bean definition inheritance
Issue: SPR-16602 (cherry picked from commit 914b247)
1 parent b8c92ce commit 8818176

File tree

3 files changed

+70
-36
lines changed

3 files changed

+70
-36
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,12 @@
3535
* {@link Bean @Bean}, {@code @Scope} indicates the name of a scope to use
3636
* for the instance returned from the method.
3737
*
38+
* <p><b>NOTE:</b> {@code @Scope} annotations are only introspected on the
39+
* concrete bean class (for annotated components) or the factory method
40+
* (for {@code @Bean} methods). In contrast to XML bean definitions,
41+
* there is no notion of bean definition inheritance, and inheritance
42+
* hierarchies at the class level are irrelevant for metadata purposes.
43+
*
3844
* <p>In this context, <em>scope</em> means the lifecycle of an instance,
3945
* such as {@code singleton}, {@code prototype}, and so forth. Scopes
4046
* provided out of the box in Spring may be referred to using the

spring-context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -1452,9 +1452,19 @@ public void testInnerBeanInheritsScopeFromConcreteChildDefinition() {
14521452
DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
14531453
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
14541454
reader.loadBeanDefinitions(OVERRIDES_CONTEXT);
1455-
TestBean jenny = (TestBean) xbf.getBean("jennyChild");
1456-
assertEquals(1, jenny.getFriends().size());
1457-
assertTrue(jenny.getFriends().iterator().next() instanceof TestBean);
1455+
1456+
TestBean jenny1 = (TestBean) xbf.getBean("jennyChild");
1457+
assertEquals(1, jenny1.getFriends().size());
1458+
Object friend1 = jenny1.getFriends().iterator().next();
1459+
assertTrue(friend1 instanceof TestBean);
1460+
1461+
TestBean jenny2 = (TestBean) xbf.getBean("jennyChild");
1462+
assertEquals(1, jenny2.getFriends().size());
1463+
Object friend2 = jenny2.getFriends().iterator().next();
1464+
assertTrue(friend2 instanceof TestBean);
1465+
1466+
assertNotSame(jenny1, jenny2);
1467+
assertNotSame(friend1, friend2);
14581468
}
14591469

14601470
@Test

src/asciidoc/core-beans.adoc

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -306,23 +306,23 @@ Typically, such configuration will live in a ".groovy" file with a structure as
306306
[source,java,indent=0]
307307
[subs="verbatim,quotes"]
308308
----
309-
beans {
310-
dataSource(BasicDataSource) {
311-
driverClassName = "org.hsqldb.jdbcDriver"
312-
url = "jdbc:hsqldb:mem:grailsDB"
313-
username = "sa"
314-
password = ""
315-
settings = [mynew:"setting"]
316-
}
317-
sessionFactory(SessionFactory) {
318-
dataSource = dataSource
319-
}
320-
myService(MyService) {
321-
nestedBean = { AnotherBean bean ->
322-
dataSource = dataSource
323-
}
324-
}
325-
}
309+
beans {
310+
dataSource(BasicDataSource) {
311+
driverClassName = "org.hsqldb.jdbcDriver"
312+
url = "jdbc:hsqldb:mem:grailsDB"
313+
username = "sa"
314+
password = ""
315+
settings = [mynew:"setting"]
316+
}
317+
sessionFactory(SessionFactory) {
318+
dataSource = dataSource
319+
}
320+
myService(MyService) {
321+
nestedBean = { AnotherBean bean ->
322+
dataSource = dataSource
323+
}
324+
}
325+
}
326326
----
327327

328328
This configuration style is largely equivalent to XML bean definitions and even
@@ -4469,17 +4469,17 @@ The same applies for typed collections:
44694469
====
44704470
Your target beans can implement the `org.springframework.core.Ordered` interface or use
44714471
the `@Order` or standard `@Priority` annotation if you want items in the array or list
4472-
to be sorted into a specific order. Otherwise their order will follow the registration
4472+
to be sorted in a specific order. Otherwise their order will follow the registration
44734473
order of the corresponding target bean definitions in the container.
44744474
44754475
The `@Order` annotation may be declared at target class level but also on `@Bean` methods,
44764476
potentially being very individual per bean definition (in case of multiple definitions
4477-
with the same bean class). `@Order` values may influence priorities at injection points
4477+
with the same bean class). `@Order` values may influence priorities at injection points,
44784478
but please be aware that they do not influence singleton startup order which is an
44794479
orthogonal concern determined by dependency relationships and `@DependsOn` declarations.
44804480
44814481
Note that the standard `javax.annotation.Priority` annotation is not available at the
4482-
`@Bean` level since it cannot be declared on methods. Its semantics can be modelled
4482+
`@Bean` level since it cannot be declared on methods. Its semantics can be modeled
44834483
through `@Order` values in combination with `@Primary` on a single bean per type.
44844484
====
44854485

@@ -5731,10 +5731,10 @@ Spring stereotype annotation (`@Component`, `@Repository`, `@Service`, and
57315731
`@Controller`) that contains a _name_ `value` will thereby provide that name to the
57325732
corresponding bean definition.
57335733

5734-
If such an annotation contains no _name_ `value` or for any other detected component (such
5735-
as those discovered by custom filters), the default bean name generator returns the
5736-
uncapitalized non-qualified class name. For example, if the following two components
5737-
were detected, the names would be `myMovieLister` and `movieFinderImpl`:
5734+
If such an annotation contains no _name_ `value` or for any other detected component
5735+
(such as those discovered by custom filters), the default bean name generator returns
5736+
the uncapitalized non-qualified class name. For example, if the following component
5737+
classes were detected, the names would be `myMovieLister` and `movieFinderImpl`:
57385738

57395739
[source,java,indent=0]
57405740
[subs="verbatim,quotes"]
@@ -5793,8 +5793,8 @@ auto-generated names are adequate whenever the container is responsible for wiri
57935793

57945794
As with Spring-managed components in general, the default and most common scope for
57955795
autodetected components is `singleton`. However, sometimes you need a different scope
5796-
which can be specified via the `@Scope` annotation. Simply provide the name of the scope
5797-
within the annotation:
5796+
which can be specified via the `@Scope` annotation. Simply provide the name of the
5797+
scope within the annotation:
57985798

57995799
[source,java,indent=0]
58005800
[subs="verbatim,quotes"]
@@ -5806,8 +5806,19 @@ within the annotation:
58065806
}
58075807
----
58085808

5809-
For details on web-specific scopes, see <<beans-factory-scopes-other>>.
5809+
[NOTE]
5810+
====
5811+
`@Scope` annotations are only introspected on the concrete bean class (for annotated
5812+
components) or the factory method (for `@Bean` methods). In contrast to XML bean
5813+
definitions, there is no notion of bean definition inheritance, and inheritance
5814+
hierarchies at the class level are irrelevant for metadata purposes.
5815+
====
58105816

5817+
For details on web-specific scopes such as "request"/"session" in a Spring context,
5818+
see <<beans-factory-scopes-other>>. Like the pre-built annotations for those scopes,
5819+
you may also compose your own scoping annotations using Spring's meta-annotation
5820+
approach: e.g. a custom annotation meta-annotated with `@Scope("prototype")`,
5821+
possibly also declaring a custom scoped-proxy mode.
58115822

58125823
[NOTE]
58135824
====
@@ -5832,8 +5843,7 @@ fully-qualified class name when configuring the scanner:
58325843
[subs="verbatim,quotes"]
58335844
----
58345845
<beans>
5835-
<context:component-scan base-package="org.example"
5836-
scope-resolver="org.example.MyScopeResolver" />
5846+
<context:component-scan base-package="org.example" scope-resolver="org.example.MyScopeResolver"/>
58375847
</beans>
58385848
----
58395849

@@ -5857,8 +5867,7 @@ the following configuration will result in standard JDK dynamic proxies:
58575867
[subs="verbatim,quotes"]
58585868
----
58595869
<beans>
5860-
<context:component-scan base-package="org.example"
5861-
scoped-proxy="interfaces" />
5870+
<context:component-scan base-package="org.example" scoped-proxy="interfaces"/>
58625871
</beans>
58635872
----
58645873

@@ -7976,6 +7985,15 @@ be resolved to the corresponding value. If not, then "default/path" will be used
79767985
as a default. If no default is specified and a property cannot be resolved, an
79777986
`IllegalArgumentException` will be thrown.
79787987

7988+
[NOTE]
7989+
====
7990+
The `@PropertySource` annotation is repeatable according to Java 8 conventions.
7991+
However, all such `@PropertySource` annotations need to be declared at the same
7992+
level: either directly on the configuration class or as meta-annotations within the
7993+
same custom annotation. Mixing of direct annotations and meta-annotations is not
7994+
recommended since direct annotations will effectively override meta-annotations.
7995+
====
7996+
79797997

79807998

79817999
=== Placeholder resolution in statements

0 commit comments

Comments
 (0)