Basic Concepts: @Bean
and @Configuration
Spring 的 Java 配置支持中的核心构件是使用 @Configuration
进行注解的类和使用 @Bean
进行注解的方法。
The central artifacts in Spring’s Java configuration support are
@Configuration
-annotated classes and @Bean
-annotated methods.
@Bean
注解用于指示一个方法实例化、配置和初始化一个由 Spring IoC 容器管理的新对象。对于熟悉 Spring 的 <beans/>
XML 配置的用户而言,@Bean
注解所扮演的角色与 <bean/>
元素相同。你可以在任何 Spring @Component
中使用使用 @Bean
进行注解的方法。但是,它们最常与 @Configuration
bean 一起使用。
The @Bean
annotation is used to indicate that a method instantiates, configures, and
initializes a new object to be managed by the Spring IoC container. For those familiar
with Spring’s <beans/>
XML configuration, the @Bean
annotation plays the same role as
the <bean/>
element. You can use @Bean
-annotated methods with any Spring
@Component
. However, they are most often used with @Configuration
beans.
使用 @Configuration
对一个类进行注解表示其主要用途是作为 bean 定义的来源。此外,@Configuration
类允许通过在同一个类中调用其他 @Bean
方法来定义 bean 之间的依赖关系。最简单的 @Configuration
类可以按如下方式编写:
Annotating a class with @Configuration
indicates that its primary purpose is as a
source of bean definitions. Furthermore, @Configuration
classes let inter-bean
dependencies be defined by calling other @Bean
methods in the same class.
The simplest possible @Configuration
class reads as follows:
-
Java
-
Kotlin
@Configuration
public class AppConfig {
@Bean
public MyServiceImpl myService() {
return new MyServiceImpl();
}
}
@Configuration
class AppConfig {
@Bean
fun myService(): MyServiceImpl {
return MyServiceImpl()
}
}
前面的 AppConfig
类等效于以下 Spring <beans/>
XML:
The preceding AppConfig
class is equivalent to the following Spring <beans/>
XML:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
在常见场景中,@Bean
方法应在 @Configuration
类中声明,以确保应用完全的配置类处理,并让交叉方法引用因此重定向到容器的生命周期管理。这可以防止同一个 @Bean
方法意外地通过常规 Java 方法调用被调用,从而有助于减少难以跟踪的细微差别错误。
In common scenarios, @Bean
methods are to be declared within @Configuration
classes,
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.
如果 @Bean
方法在未使用 @Configuration
进行注解的类中声明(或者当声明 @Configuration(proxyBeanMethods=false)
时),它们被称作以“精简”模式得到处理。在这种场景中,@Bean
方法实际上是一种通用工厂方法机制,没有特殊的运行时处理(即,不为它生成 CGLIB 的子类)。容器不会拦截对这种方法的自定义 Java 调用,因此行为就如同一个常规的方法调用,每次创建新实例,而不是为给定的 bean 重用现有的单例(或作用域)实例。
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.
结果,不进行运行时代理的类上的 @Bean
方法根本不应声明 bean 之间的依赖关系。相反,它们应该在其组件的字段上(或者可以选择在工厂方法中声明的参数上)运行,以便接收自动注入的协作者。因此,这种 @Bean
方法永远不需要调用其他 @Bean
方法;每个这样的调用可以通过一个工厂方法参数进行表达。其积极的副作用是,不必在运行时应用 CGLIB 子类化,从而减少了开销和占用空间。
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.
以下章节将深入讨论 @Bean
和 @Configuration
注解。然而,首先,我们将介绍使用基于 Java 的配置来创建 Spring 容器的不同方式。
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
Java-based configuration.