此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
使用@Bean
注解
@Bean
是方法级注释,是 XML 的直接模拟<bean/>
元素。 注释支持<bean/>
如:
-
name
.
您可以使用@Bean
注释@Configuration
-注释或在@Component
-annotated 类。
声明 Bean
要声明 bean,您可以使用@Bean
注解。 您可以使用此方法在ApplicationContext
的类型指定为方法的返回值。默认情况下,bean 名称与方法名称相同。以下示例显示了@Bean
方法声明:
-
Java
-
Kotlin
@Configuration
public class AppConfig {
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
@Configuration
class AppConfig {
@Bean
fun transferService() = TransferServiceImpl()
}
前面的配置完全等同于下面的 Spring XML:
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
这两个声明都使一个名为transferService
在ApplicationContext
,绑定到类型为TransferServiceImpl
,作为以下文本图像显示:
transferService -> com.acme.TransferServiceImpl
您还可以使用默认方法来定义 bean。这允许组合 bean通过在默认方法上实现具有 bean 定义的接口来配置。
-
Java
public interface BaseConfig {
@Bean
default TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
@Configuration
public class AppConfig implements BaseConfig {
}
您还可以声明您的@Bean
方法与接口(或基类)返回类型,如以下示例所示:
-
Java
-
Kotlin
@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
, 它仅解析一次transferService
bean 已被实例化)。
如果您始终通过声明的服务接口引用您的类型,则您的@Bean 返回类型可以安全地加入该设计决策。但是,对于实现多个接口的组件或对于可能由其实现类型引用的组件,声明最具体的返回类型可能更安全(至少与引用 bean 的注入点所需的具体性一样具体)。 |
Bean 依赖项
一个@Bean
-annotated 方法可以有任意数量的参数来描述构建该 bean 所需的依赖关系。例如,如果我们的TransferService
需要一个AccountRepository
,我们可以使用方法参数实现该依赖关系,如以下示例所示:
-
Java
-
Kotlin
@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)
}
}
解析机制与基于构造函数的依赖关系几乎相同 注射。 有关更多详细信息,请参阅相关部分。
接收生命周期回传
使用@Bean
注解支持常规生命周期回调
并且可以使用@PostConstruct
和@PreDestroy
JSR-250 的注释。有关进一步的信息,请参阅 JSR-250 注释
详。
常规的 Spring 生命周期回调完全支持
井。如果 bean 实现InitializingBean
,DisposableBean
或Lifecycle
他们
容器调用相应的方法。
标准集*Aware
接口(例如 BeanFactoryAware、BeanNameAware、MessageSourceAware、ApplicationContextAware 等)也完全受支持。
这@Bean
注解支持指定任意初始化和销毁
回调方法,很像 Spring XML 的init-method
和destroy-method
属性
在bean
元素,如以下示例所示:
-
Java
-
Kotlin
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 具有 public 默认情况下,您可能希望对使用 JNDI 获取的资源执行此作,因为它的
生命周期在应用程序外部进行管理。特别是,确保始终这样做
对于一个 以下示例显示了如何防止
此外,与 |
在以下情况下BeanOne
从前面注释上面的示例来看,它将是
同样有效调用init()
方法直接在施工过程中,作为
以下示例显示:
-
Java
-
Kotlin
@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 的作用域。
使用@Scope
注解
您可以指定使用@Bean
注释应该有一个
具体范围。您可以使用 Bean 作用域部分中指定的任何标准作用域。
默认范围为singleton
,但您可以使用@Scope
注解
如以下示例所示:
-
Java
-
Kotlin
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Encryptor encryptor() {
// ...
}
}
@Configuration
class MyConfiguration {
@Bean
@Scope("prototype")
fun encryptor(): Encryptor {
// ...
}
}
@Scope
和scoped-proxy
Spring 提供了一种通过作用域代理处理作用域依赖关系的便捷方法。创建使用 XML 配置时,此类代理是<aop:scoped-proxy/>
元素。 使用@Scope
注释提供等效支持使用proxyMode
属性。 默认值为ScopedProxyMode.DEFAULT
哪 通常表示不应创建作用域代理,除非在组件扫描指令级别配置了不同的默认值。您可以指定ScopedProxyMode.TARGET_CLASS
,ScopedProxyMode.INTERFACES
或ScopedProxyMode.NO
.
如果您将作用域代理示例从 XML 参考文档(请参阅作用域代理)移植到我们的@Bean
使用 Java,它类似于以下内容:
-
Java
-
Kotlin
// 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
属性 如以下示例所示:
-
Java
-
Kotlin
@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
属性的@Bean
annotation 为此目的接受 String 数组。
以下示例显示了如何为 Bean 设置多个别名:
-
Java
-
Kotlin
@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)用于监控目的时特别有用。
要将描述添加到@Bean
,您可以使用@Description
注释,如以下示例所示:
-
Java
-
Kotlin
@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()
}