对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

使用@Bean注解

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

您可以使用@Bean注解@Configuration-annotated 或@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

您还可以使用 default 方法来定义 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具有接口(或基类)的方法 return 类型,如下例所示: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) 仅在实例化受影响的 singleton bean 后,容器才知道。 非惰性单例 bean 根据它们的声明顺序进行实例化, 因此,您可能会看到不同的类型匹配结果,具体取决于另一个组件的时间 尝试通过未声明的类型(例如@Autowired TransferServiceImpl, 它仅在transferServicebean 已被实例化)。spring-doc.cadn.net.cn

如果您始终通过声明的服务接口引用您的类型,则您的@Bean返回类型可以安全地加入该设计决策。但是,对于组件 实现多个接口,或者对于可能由其 implementation 类型,则声明最具体的返回类型会更安全 (至少与引用 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

接收生命周期回调

任何使用@Beanannotation 支持常规生命周期回调 ,并且可以使用@PostConstruct@PreDestroy来自 JSR-250 的注释。有关详细信息,请参阅 JSR-250 注释 详。spring-doc.cadn.net.cn

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

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

@Beanannotation 支持指定任意初始化和析构 回调方法,很像 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 具有公共closeshutdown方法会自动使用销毁回调登记。如果您有公共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帮助程序或直接 JNDIInitialContextusage 一起使用,但不是JndiObjectFactoryBean变体(这将强制 U 将返回类型声明为FactoryBeantype 而不是实际目标 type,使其更难用于其他@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 Scopes 部分中指定的任何标准范围。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/>元素。 在 Java 中使用@ScopeAnnotation 提供等效支持 使用proxyMode属性。默认值为ScopedProxyMode.DEFAULT哪 通常表示不应创建作用域代理,除非使用不同的默认值 已在 component-scan 指令级别进行配置。您可以指定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 命名

默认情况下,配置类使用@Beanmethod's name 作为 结果 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 别名

正如命名 Bean 中所讨论的,它是 有时需要为单个 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,您可以使用@Descriptionannotation 中,如下例所示: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()
}