此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

使用@Bean注解

@Bean是方法级注释,是 XML 的直接模拟<bean/>元素。 注释支持<bean/>如:spring-doc.cadn.net.cn

您可以使用@Bean注释@Configuration-注释或在@Component-annotated 类。spring-doc.cadn.net.cn

声明 Bean

要声明 bean,您可以使用@Bean注解。 您可以使用此方法在ApplicationContext的类型指定为方法的返回值。默认情况下,bean 名称与方法名称相同。以下示例显示了@Bean方法声明:spring-doc.cadn.net.cn

@Configuration
public class AppConfig {

	@Bean
	public TransferServiceImpl transferService() {
		return new TransferServiceImpl();
	}
}
@Configuration
class AppConfig {

	@Bean
	fun transferService() = TransferServiceImpl()
}

前面的配置完全等同于下面的 Spring XML:spring-doc.cadn.net.cn

<beans>
	<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

这两个声明都使一个名为transferServiceApplicationContext,绑定到类型为TransferServiceImpl,作为以下文本图像显示:spring-doc.cadn.net.cn

transferService -> com.acme.TransferServiceImpl

您还可以使用默认方法来定义 bean。这允许组合 bean通过在默认方法上实现具有 bean 定义的接口来配置。spring-doc.cadn.net.cn

public interface BaseConfig {

	@Bean
	default TransferServiceImpl transferService() {
		return new TransferServiceImpl();
	}
}

@Configuration
public class AppConfig implements BaseConfig {

}

您还可以声明您的@Bean方法与接口(或基类)返回类型,如以下示例所示:spring-doc.cadn.net.cn

@Configuration
public class AppConfig {

	@Bean
	public TransferService transferService() {
		return new TransferServiceImpl();
	}
}
@Configuration
class AppConfig {

	@Bean
	fun transferService(): TransferService {
		return TransferServiceImpl()
	}
}

但是,这会将高级类型预测的可见性限制为指定的接口类型 (TransferService). 然后,使用完整类型 (TransferServiceImpl) 只有在受影响的单例 Bean 被实例化后,容器才知道。非惰性单例 Bean 根据其声明顺序进行实例化,因此,您可能会看到不同的类型匹配结果,具体取决于另一个组件何时尝试通过非声明的类型(例如@Autowired TransferServiceImpl, 它仅解析一次transferServicebean 已被实例化)。spring-doc.cadn.net.cn

如果您始终通过声明的服务接口引用您的类型,则您的@Bean返回类型可以安全地加入该设计决策。但是,对于实现多个接口的组件或对于可能由其实现类型引用的组件,声明最具体的返回类型可能更安全(至少与引用 bean 的注入点所需的具体性一样具体)。

Bean 依赖项

一个@Bean-annotated 方法可以有任意数量的参数来描述构建该 bean 所需的依赖关系。例如,如果我们的TransferService需要一个AccountRepository,我们可以使用方法参数实现该依赖关系,如以下示例所示:spring-doc.cadn.net.cn

@Configuration
public class AppConfig {

	@Bean
	public TransferService transferService(AccountRepository accountRepository) {
		return new TransferServiceImpl(accountRepository);
	}
}
@Configuration
class AppConfig {

	@Bean
	fun transferService(accountRepository: AccountRepository): TransferService {
		return TransferServiceImpl(accountRepository)
	}
}

解析机制与基于构造函数的依赖关系几乎相同 注射。 有关更多详细信息,请参阅相关部分spring-doc.cadn.net.cn

接收生命周期回传

使用@Bean注解支持常规生命周期回调 并且可以使用@PostConstruct@PreDestroyJSR-250 的注释。有关进一步的信息,请参阅 JSR-250 注释 详。spring-doc.cadn.net.cn

常规的 Spring 生命周期回调完全支持 井。如果 bean 实现InitializingBean,DisposableBeanLifecycle他们 容器调用相应的方法。spring-doc.cadn.net.cn

标准集*Aware接口(例如 BeanFactoryAwareBeanNameAwareMessageSourceAwareApplicationContextAware 等)也完全受支持。spring-doc.cadn.net.cn

@Bean注解支持指定任意初始化和销毁 回调方法,很像 Spring XML 的init-methoddestroy-method属性 在bean元素,如以下示例所示:spring-doc.cadn.net.cn

public class BeanOne {

	public void init() {
		// initialization logic
	}
}

public class BeanTwo {

	public void cleanup() {
		// destruction logic
	}
}

@Configuration
public class AppConfig {

	@Bean(initMethod = "init")
	public BeanOne beanOne() {
		return new BeanOne();
	}

	@Bean(destroyMethod = "cleanup")
	public BeanTwo beanTwo() {
		return new BeanTwo();
	}
}
class BeanOne {

	fun init() {
		// initialization logic
	}
}

class BeanTwo {

	fun cleanup() {
		// destruction logic
	}
}

@Configuration
class AppConfig {

	@Bean(initMethod = "init")
	fun beanOne() = BeanOne()

	@Bean(destroyMethod = "cleanup")
	fun beanTwo() = BeanTwo()
}

默认情况下,使用 Java 配置定义的 bean 具有 publiccloseshutdown方法会自动注册销毁回调。如果您有公共closeshutdown方法,并且您不希望在容器 关闭时,您可以添加@Bean(destroyMethod = "")添加到您的 Bean 定义以禁用 违约(inferred)模式。spring-doc.cadn.net.cn

默认情况下,您可能希望对使用 JNDI 获取的资源执行此作,因为它的 生命周期在应用程序外部进行管理。特别是,确保始终这样做 对于一个DataSource,因为众所周知,它在 Jakarta EE 应用程序服务器上存在问题。spring-doc.cadn.net.cn

以下示例显示了如何防止DataSource:spring-doc.cadn.net.cn

@Bean(destroyMethod = "")
public DataSource dataSource() throws NamingException {
	return (DataSource) jndiTemplate.lookup("MyDS");
}
@Bean(destroyMethod = "")
fun dataSource(): DataSource {
	return jndiTemplate.lookup("MyDS") as DataSource
}

此外,与@Bean方法,您通常使用编程 JNDI 查找,通过 使用 Spring 的JndiTemplateJndiLocatorDelegate辅助程序或直接 JNDIInitialContext用法,但不是JndiObjectFactoryBean变体(这将强制 您将返回类型声明为FactoryBeantype 而不是实际目标 类型,使其更难用于其他@Bean方法 打算在此处参考提供的资源)。spring-doc.cadn.net.cn

在以下情况下BeanOne从前面注释上面的示例来看,它将是 同样有效调用init()方法直接在施工过程中,作为 以下示例显示:spring-doc.cadn.net.cn

@Configuration
public class AppConfig {

	@Bean
	public BeanOne beanOne() {
		BeanOne beanOne = new BeanOne();
		beanOne.init();
		return beanOne;
	}

	// ...
}
@Configuration
class AppConfig {

	@Bean
	fun beanOne() = BeanOne().apply {
		init()
	}

	// ...
}
当您直接在 Java 中工作时,您可以对对象做任何您喜欢的事情,并执行以下作 并不总是需要依赖容器生命周期。

指定 Bean 作用域

Spring 包括@Scope注释,以便您可以指定 bean 的作用域。spring-doc.cadn.net.cn

使用@Scope注解

您可以指定使用@Bean注释应该有一个 具体范围。您可以使用 Bean 作用域部分中指定的任何标准作用域。spring-doc.cadn.net.cn

默认范围为singleton,但您可以使用@Scope注解 如以下示例所示:spring-doc.cadn.net.cn

@Configuration
public class MyConfiguration {

	@Bean
	@Scope("prototype")
	public Encryptor encryptor() {
		// ...
	}
}
@Configuration
class MyConfiguration {

	@Bean
	@Scope("prototype")
	fun encryptor(): Encryptor {
		// ...
	}
}

@Scopescoped-proxy

Spring 提供了一种通过作用域代理处理作用域依赖关系的便捷方法。创建使用 XML 配置时,此类代理是<aop:scoped-proxy/>元素。 使用@Scope注释提供等效支持使用proxyMode属性。 默认值为ScopedProxyMode.DEFAULT哪 通常表示不应创建作用域代理,除非在组件扫描指令级别配置了不同的默认值。您可以指定ScopedProxyMode.TARGET_CLASS,ScopedProxyMode.INTERFACESScopedProxyMode.NO.spring-doc.cadn.net.cn

如果您将作用域代理示例从 XML 参考文档(请参阅作用域代理)移植到我们的@Bean使用 Java,它类似于以下内容:spring-doc.cadn.net.cn

// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
	return new UserPreferences();
}

@Bean
public Service userService() {
	UserService service = new SimpleUserService();
	// a reference to the proxied userPreferences bean
	service.setUserPreferences(userPreferences());
	return service;
}
// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
fun userPreferences() = UserPreferences()

@Bean
fun userService(): Service {
	return SimpleUserService().apply {
		// a reference to the proxied userPreferences bean
		setUserPreferences(userPreferences())
	}
}

自定义 Bean 命名

默认情况下,配置类使用@Bean方法的名称作为生成的 bean 的名称。但是,可以使用name属性 如以下示例所示:spring-doc.cadn.net.cn

@Configuration
public class AppConfig {

	@Bean("myThing")
	public Thing thing() {
		return new Thing();
	}
}
@Configuration
class AppConfig {

	@Bean("myThing")
	fun thing() = Thing()
}

Bean 混叠

正如命名 Beans 中所讨论的,它是 有时需要为单个 Bean 指定多个名称,也称为 Bean 别名。 这name属性的@Beanannotation 为此目的接受 String 数组。 以下示例显示了如何为 Bean 设置多个别名:spring-doc.cadn.net.cn

@Configuration
public class AppConfig {

	@Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
	public DataSource dataSource() {
		// instantiate, configure and return DataSource bean...
	}
}
@Configuration
class AppConfig {

	@Bean("dataSource", "subsystemA-dataSource", "subsystemB-dataSource")
	fun dataSource(): DataSource {
		// instantiate, configure and return DataSource bean...
	}
}

Bean 描述

有时,提供 bean 的更详细的文本描述会很有帮助。这可以 当 bean 被公开(可能通过 JMX)用于监控目的时特别有用。spring-doc.cadn.net.cn

要将描述添加到@Bean,您可以使用@Description注释,如以下示例所示:spring-doc.cadn.net.cn

@Configuration
public class AppConfig {

	@Bean
	@Description("Provides a basic example of a bean")
	public Thing thing() {
		return new Thing();
	}
}
@Configuration
class AppConfig {

	@Bean
	@Description("Provides a basic example of a bean")
	fun thing() = Thing()
}