Revise IoC container introduction for modern configuration styles
Includes @Configuration(proxyBeanMethods=false) documentation. Closes gh-32429
This commit is contained in:
parent
0eb937a866
commit
9376e6322d
|
@ -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"]
|
||||
----
|
||||
|
|
|
@ -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 `<bean/>` elements inside a top-level `<beans/>` 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 `<bean/>` elements inside
|
||||
a top-level `<beans/>` 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 `<import/>` 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
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -55,33 +55,34 @@ The preceding `AppConfig` class is equivalent to the following Spring `<beans/>`
|
|||
</beans>
|
||||
----
|
||||
|
||||
.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.
|
||||
|
||||
|
||||
|
|
|
@ -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].
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue