基本概念:@Bean@Configuration

Spring 的 Java 配置支持的核心构件是使用 @Configuration 注解的类和使用 @Bean 注解的方法。

@Bean 注解用于指示某个方法实例化、配置并初始化一个新对象,该对象将由 Spring IoC 容器管理。对于熟悉 Spring <beans/> XML 配置的人来说,@Bean 注解扮演的角色与 <bean/> 元素相同。你可以在任何 Spring @Component 中使用带有 @Bean 注解的方法。但是,它们最常与 @Configuration bean 一起使用。

使用 @Configuration 注解类表明其主要用途是作为 bean 定义的来源。此外,@Configuration 类允许通过调用同一类中的其他 @Bean 方法来定义 bean 之间的依赖关系。最简单的 @Configuration 类如下所示:

  • 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:

<beans>
	<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
带或不带 @Bean 方法之间本地调用的 @Configuration 类?

在常见场景中,@Bean 方法应声明在 @Configuration 类中,以确保完整的配置类处理得以应用,并且跨方法引用因此会被重定向到容器的生命周期管理。这可以防止同一 @Bean 方法通过常规的 Java 方法调用意外被调用,这有助于减少难以追踪的细微错误。

@Bean 方法声明在没有使用 @Configuration 注解的类中,或者声明了 @Configuration(proxyBeanMethods=false) 时,它们被称为在“lite”模式下处理。在这种情况下,@Bean 方法实际上是一种通用的工厂方法机制,没有特殊的运行时处理(即不会为其生成 CGLIB 子类)。对这种方法进行的自定义 Java 调用不会被容器拦截,因此其行为就像普通的 方法调用一样,每次都会创建一个新实例,而不是复用给定 bean 的现有单例(或作用域)实例。

因此,没有运行时代理的类中的 @Bean 方法根本不用于声明 bean 之间的依赖关系。相反,它们应操作其包含组件的字段,并且可以选择操作工厂方法可能声明的参数以接收自动装配的协作者。因此,这样的 @Bean 方法永远不需要调用其他 @Bean 方法;每个这样的调用都可以通过工厂方法参数来表达。这样做的积极副作用是运行时无需应用 CGLIB 子类化,从而降低了开销和占用空间。

在接下来的章节中,将深入讨论 @Bean@Configuration 注解。但是,首先我们将介绍使用基于 Java 的配置创建 Spring 容器的各种方法。