From 9376e6322d6616a6aea68a10f261b0b866e0186e Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 8 May 2024 17:51:25 +0200 Subject: [PATCH] Revise IoC container introduction for modern configuration styles Includes @Configuration(proxyBeanMethods=false) documentation. Closes gh-32429 --- .../pages/core/beans/annotation-config.adoc | 48 ++++------ .../modules/ROOT/pages/core/beans/basics.adoc | 89 ++++++++----------- .../pages/core/beans/java/basic-concepts.adoc | 45 +++++----- .../modules/ROOT/pages/languages/groovy.adoc | 2 +- .../ctx-management/groovy.adoc | 2 +- 5 files changed, 79 insertions(+), 107 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/beans/annotation-config.adoc b/framework-docs/modules/ROOT/pages/core/beans/annotation-config.adoc index 5646f153fe..f364ae8ed1 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/annotation-config.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/annotation-config.adoc @@ -1,33 +1,16 @@ [[beans-annotation-config]] = Annotation-based Container Configuration -.Are annotations better than XML for configuring Spring? -**** -The introduction of annotation-based configuration raised the question of whether this -approach is "`better`" than XML. The short answer is "`it depends.`" The long answer is -that each approach has its pros and cons, and, usually, it is up to the developer to -decide which strategy suits them better. Due to the way they are defined, annotations -provide a lot of context in their declaration, leading to shorter and more concise -configuration. However, XML excels at wiring up components without touching their source -code or recompiling them. Some developers prefer having the wiring close to the source -while others argue that annotated classes are no longer POJOs and, furthermore, that the -configuration becomes decentralized and harder to control. +Spring provides comprehensive support for annotation-based configuration, operating on +metadata in the component class itself by using annotations on the relevant class, +method, or field declaration. As mentioned in +xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[Example: The `AutowiredAnnotationBeanPostProcessor`], +Spring uses `BeanPostProcessors` in conjunction with annotations to make the core IOC +container aware of specific annotations. -No matter the choice, Spring can accommodate both styles and even mix them together. -It is worth pointing out that through its xref:core/beans/java.adoc[JavaConfig] option, Spring lets -annotations be used in a non-invasive way, without touching the target components' -source code and that, in terms of tooling, all configuration styles are supported by -{spring-site-tools}[Spring Tools] for Eclipse, Visual Studio Code, and Theia. -**** - -An alternative to XML setup is provided by annotation-based configuration, which relies -on bytecode metadata for wiring up components instead of XML declarations. Instead of -using XML to describe a bean wiring, the developer moves the configuration into the -component class itself by using annotations on the relevant class, method, or field -declaration. As mentioned in xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp-examples-aabpp[Example: The `AutowiredAnnotationBeanPostProcessor`], using a -`BeanPostProcessor` in conjunction with annotations is a common means of extending the -Spring IoC container. For example, the xref:core/beans/annotation-config/autowired.adoc[`@Autowired`] -annotation provides the same capabilities as described in xref:core/beans/dependencies/factory-autowire.adoc[Autowiring Collaborators] but +For example, the xref:core/beans/annotation-config/autowired.adoc[`@Autowired`] +annotation provides the same capabilities as described in +xref:core/beans/dependencies/factory-autowire.adoc[Autowiring Collaborators] but with more fine-grained control and wider applicability. In addition, Spring provides support for JSR-250 annotations, such as `@PostConstruct` and `@PreDestroy`, as well as support for JSR-330 (Dependency Injection for Java) annotations contained in the @@ -36,13 +19,16 @@ can be found in the xref:core/beans/standard-annotations.adoc[relevant section]. [NOTE] ==== -Annotation injection is performed before XML injection. Thus, the XML configuration -overrides the annotations for properties wired through both approaches. +Annotation injection is performed before external property injection. Thus, external +configuration (e.g. XML-specified bean properties) effectively overrides the annotations +for properties when wired through mixed approaches. ==== -As always, you can register the post-processors as individual bean definitions, but they -can also be implicitly registered by including the following tag in an XML-based Spring -configuration (notice the inclusion of the `context` namespace): +Technically, you can register the post-processors as individual bean definitions, but they +are implicitly registered in an `AnnotationConfigApplicationContext` already. + +In an XML-based Spring setup, you may include the following configuration tag to enable +mixing and matching with annotation-based configuration: [source,xml,indent=0,subs="verbatim,quotes"] ---- diff --git a/framework-docs/modules/ROOT/pages/core/beans/basics.adoc b/framework-docs/modules/ROOT/pages/core/beans/basics.adoc index 0b04847b68..7102d7ada6 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/basics.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/basics.adoc @@ -2,36 +2,28 @@ = Container Overview The `org.springframework.context.ApplicationContext` interface represents the Spring IoC -container and is responsible for instantiating, configuring, and assembling the -beans. The container gets its instructions on what objects to -instantiate, configure, and assemble by reading configuration metadata. The -configuration metadata is represented in XML, Java annotations, or Java code. It lets -you express the objects that compose your application and the rich interdependencies -between those objects. +container and is responsible for instantiating, configuring, and assembling the beans. +The container gets its instructions on the components to instantiate, configure, and +assemble by reading configuration metadata. The configuration metadata can be represented +as annotated component classes, configuration classes with factory methods, or external +XML files or Groovy scripts. With either format, you may compose your application and the +rich interdependencies between those components. -Several implementations of the `ApplicationContext` interface are supplied -with Spring. In stand-alone applications, it is common to create an -instance of -{spring-framework-api}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`] -or {spring-framework-api}/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`]. -While XML has been the traditional format for defining configuration metadata, you can -instruct the container to use Java annotations or code as the metadata format by -providing a small amount of XML configuration to declaratively enable support for these -additional metadata formats. +Several implementations of the `ApplicationContext` interface are part of core Spring. +In stand-alone applications, it is common to create an instance of +{spring-framework-api}/context/annotation/AnnotationConfigApplicationContext.html[`AnnotationConfigApplicationContext`] +or {spring-framework-api}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]. In most application scenarios, explicit user code is not required to instantiate one or -more instances of a Spring IoC container. For example, in a web application scenario, a -simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file -of the application typically suffices (see +more instances of a Spring IoC container. For example, in a plain web application scenario, +a simple boilerplate web descriptor XML in the `web.xml` file of the application suffices (see xref:core/beans/context-introduction.adoc#context-create[Convenient ApplicationContext Instantiation for Web Applications]). -If you use the {spring-site-tools}[Spring Tools for Eclipse] (an Eclipse-powered -development environment), you can easily create this boilerplate configuration with a -few mouse clicks or keystrokes. +In a Spring Boot scenario, the application context is implicitly bootstrapped for you +based on common setup conventions. The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the `ApplicationContext` is -created and initialized, you have a fully configured and executable system or -application. +created and initialized, you have a fully configured and executable system or application. .The Spring IoC container image::container-magic.png[] @@ -43,33 +35,25 @@ image::container-magic.png[] As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an -application developer, tell the Spring container to instantiate, configure, and assemble -the objects in your application. +application developer, tell the Spring container to instantiate, configure, +and assemble the components in your application. -Configuration metadata is traditionally supplied in a simple and intuitive XML format, -which is what most of this chapter uses to convey key concepts and features of the -Spring IoC container. - -NOTE: XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this configuration metadata is actually written. These days, many developers choose -xref:core/beans/java.adoc[Java-based configuration] for their Spring applications. - -For information about using other forms of metadata with the Spring container, see: +xref:core/beans/java.adoc[Java-based configuration] for their Spring applications: * xref:core/beans/annotation-config.adoc[Annotation-based configuration]: define beans using - annotation-based configuration metadata. + annotation-based configuration metadata on your application's component classes. * xref:core/beans/java.adoc[Java-based configuration]: define beans external to your application - classes by using Java rather than XML files. To use these features, see the + classes by using Java-based configuration classes. To use these features, see the {spring-framework-api}/context/annotation/Configuration.html[`@Configuration`], {spring-framework-api}/context/annotation/Bean.html[`@Bean`], {spring-framework-api}/context/annotation/Import.html[`@Import`], and {spring-framework-api}/context/annotation/DependsOn.html[`@DependsOn`] annotations. -Spring configuration consists of at least one and typically more than one bean -definition that the container must manage. XML-based configuration metadata configures these -beans as `` elements inside a top-level `` element. Java -configuration typically uses `@Bean`-annotated methods within a `@Configuration` class. +Spring configuration consists of at least one and typically more than one bean definition +that the container must manage. Java configuration typically uses `@Bean`-annotated +methods within a `@Configuration` class, each corresponding to one bean definition. These bean definitions correspond to the actual objects that make up your application. Typically, you define service layer objects, persistence layer objects such as @@ -79,7 +63,14 @@ Typically, one does not configure fine-grained domain objects in the container, it is usually the responsibility of repositories and business logic to create and load domain objects. -The following example shows the basic structure of XML-based configuration metadata: + + +[[beans-factory-xml]] +=== XML as an External Configuration DSL + +XML-based configuration metadata configures these beans as `` elements inside +a top-level `` element. The following example shows the basic structure of +XML-based configuration metadata: [source,xml,indent=0,subs="verbatim,quotes"] ---- @@ -110,14 +101,9 @@ The value of the `id` attribute can be used to refer to collaborating objects. T for referring to collaborating objects is not shown in this example. See xref:core/beans/dependencies.adoc[Dependencies] for more information. - - -[[beans-factory-instantiation]] -== Instantiating a Container - -The location path or paths -supplied to an `ApplicationContext` constructor are resource strings that let -the container load configuration metadata from a variety of external resources, such +For instantiating a container, the location path or paths to the XML resource files +need to be supplied to a `ClassPathXmlApplicationContext` constructor that let the +container load configuration metadata from a variety of external resources, such as the local file system, the Java `CLASSPATH`, and so on. [tabs] @@ -209,9 +195,9 @@ xref:core/beans/dependencies.adoc[Dependencies]. It can be useful to have bean definitions span multiple XML files. Often, each individual XML configuration file represents a logical layer or module in your architecture. -You can use the application context constructor to load bean definitions from all these +You can use the `ClassPathXmlApplicationContext` constructor to load bean definitions from XML fragments. This constructor takes multiple `Resource` locations, as was shown in the -xref:core/beans/basics.adoc#beans-factory-instantiation[previous section]. Alternatively, +xref:core/beans/basics.adoc#beans-factory-xml[previous section]. Alternatively, use one or more occurrences of the `` element to load bean definitions from another file or files. The following example shows how to do so: @@ -259,7 +245,7 @@ configuration features beyond plain bean definitions are available in a selectio of XML namespaces provided by Spring -- for example, the `context` and `util` namespaces. -[[groovy-bean-definition-dsl]] +[[beans-factory-groovy]] === The Groovy Bean Definition DSL As a further example for externalized configuration metadata, bean definitions can also @@ -420,4 +406,3 @@ a dependency on a specific bean through metadata (such as an autowiring annotati - diff --git a/framework-docs/modules/ROOT/pages/core/beans/java/basic-concepts.adoc b/framework-docs/modules/ROOT/pages/core/beans/java/basic-concepts.adoc index 80794f693e..5b92778389 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/java/basic-concepts.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/java/basic-concepts.adoc @@ -55,33 +55,34 @@ The preceding `AppConfig` class is equivalent to the following Spring `` ---- -.Full @Configuration vs "`lite`" @Bean mode? +.@Configuration classes with or without local calls between @Bean methods? **** -When `@Bean` methods are declared within classes that are not annotated with -`@Configuration`, they are referred to as being processed in a "`lite`" mode. Bean methods -declared on a bean that is not annotated with `@Configuration` are considered to be "`lite`", -with a different primary purpose of the containing class and a `@Bean` method -being a sort of bonus there. For example, service components may expose management views -to the container through an additional `@Bean` method on each applicable component class. -In such scenarios, `@Bean` methods are a general-purpose factory method mechanism. - -Unlike full `@Configuration`, lite `@Bean` methods cannot declare inter-bean dependencies. -Instead, they operate on their containing component's internal state and, optionally, on -arguments that they may declare. Such a `@Bean` method should therefore not invoke other -`@Bean` methods. Each such method is literally only a factory method for a particular -bean reference, without any special runtime semantics. The positive side-effect here is -that no CGLIB subclassing has to be applied at runtime, so there are no limitations in -terms of class design (that is, the containing class may be `final` and so forth). - In common scenarios, `@Bean` methods are to be declared within `@Configuration` classes, -ensuring that "`full`" mode is always used and that cross-method references therefore -get redirected to the container's lifecycle management. This prevents the same -`@Bean` method from accidentally being invoked through a regular Java call, which helps -to reduce subtle bugs that can be hard to track down when operating in "`lite`" mode. +ensuring that full configuration class processing applies and that cross-method +references therefore get redirected to the container's lifecycle management. +This prevents the same `@Bean` method from accidentally being invoked through a regular +Java method call, which helps to reduce subtle bugs that can be hard to track down. + +When `@Bean` methods are declared within classes that are not annotated with +`@Configuration` - or when `@Configuration(proxyBeanMethods=false)` is declared -, +they are referred to as being processed in a "lite" mode. In such scenarios, +`@Bean` methods are effectively a general-purpose factory method mechanism without +special runtime processing (that is, without generating a CGLIB subclass for it). +A custom Java call to such a method will not get intercepted by the container and +therefore behaves just like a regular method call, creating a new instance every time +rather than reusing an existing singleton (or scoped) instance for the given bean. + +As a consequence, `@Bean` methods on classes without runtime proxying are not meant to +declare inter-bean dependencies at all. Instead, they are expected to operate on their +containing component's fields and, optionally, on arguments that a factory method may +declare in order to receive autowired collaborators. Such a `@Bean` method therefore +never needs to invoke other `@Bean` methods; every such call can be expressed through +a factory method argument instead. The positive side-effect here is that no CGLIB +subclassing has to be applied at runtime, reducing the overhead and the footprint. **** The `@Bean` and `@Configuration` annotations are discussed in depth in the following sections. -First, however, we cover the various ways of creating a spring container by using +First, however, we cover the various ways of creating a Spring container by using Java-based configuration. diff --git a/framework-docs/modules/ROOT/pages/languages/groovy.adoc b/framework-docs/modules/ROOT/pages/languages/groovy.adoc index 745101a993..e50f136b23 100644 --- a/framework-docs/modules/ROOT/pages/languages/groovy.adoc +++ b/framework-docs/modules/ROOT/pages/languages/groovy.adoc @@ -8,7 +8,7 @@ existing Java application. The Spring Framework provides a dedicated `ApplicationContext` that supports a Groovy-based Bean Definition DSL. For more details, see -xref:core/beans/basics.adoc#groovy-bean-definition-dsl[The Groovy Bean Definition DSL]. +xref:core/beans/basics.adoc#beans-factory-groovy[The Groovy Bean Definition DSL]. Further support for Groovy, including beans written in Groovy, refreshable script beans, and more is available in xref:languages/dynamic.adoc[Dynamic Language Support]. diff --git a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/groovy.adoc b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/groovy.adoc index 9049bfc9ee..443a89fb38 100644 --- a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/groovy.adoc +++ b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/groovy.adoc @@ -2,7 +2,7 @@ = Context Configuration with Groovy Scripts To load an `ApplicationContext` for your tests by using Groovy scripts that use the -xref:core/beans/basics.adoc#groovy-bean-definition-dsl[Groovy Bean Definition DSL], you can annotate +xref:core/beans/basics.adoc#beans-factory-groovy[Groovy Bean Definition DSL], you can annotate your test class with `@ContextConfiguration` and configure the `locations` or `value` attribute with an array that contains the resource locations of Groovy scripts. Resource lookup semantics for Groovy scripts are the same as those described for