对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
使用@Bean
注解
@Bean
是方法级注释,是 XML 的直接模拟<bean/>
元素。
该注释支持<bean/>
如:
-
name
.
您可以使用@Bean
注解@Configuration
-annotated 或@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
您还可以使用 default 方法来定义 bean。这允许 bean 的组成 通过在默认方法上实现具有 bean 定义的接口来配置。
-
Java
public interface BaseConfig {
@Bean
default TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
@Configuration
public class AppConfig implements BaseConfig {
}
您还可以声明@Bean
具有接口(或基类)的方法
return 类型,如下例所示:
-
Java
-
Kotlin
@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
,
它仅在transferService
bean 已被实例化)。
如果您始终通过声明的服务接口引用您的类型,则您的@Bean 返回类型可以安全地加入该设计决策。但是,对于组件
实现多个接口,或者对于可能由其
implementation 类型,则声明最具体的返回类型会更安全
(至少与引用 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
annotation 支持常规生命周期回调
,并且可以使用@PostConstruct
和@PreDestroy
来自 JSR-250 的注释。有关详细信息,请参阅 JSR-250 注释
详。
常规的 Spring 生命周期回调完全支持为
井。如果 Bean 实现了InitializingBean
,DisposableBean
或Lifecycle
他们
容器调用相应的方法。
标准的*Aware
接口(例如 BeanFactoryAware、BeanNameAware、MessageSourceAware、ApplicationContext Aware 等)也完全受支持。
这@Bean
annotation 支持指定任意初始化和析构
回调方法,很像 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 具有公共 默认情况下,您可能希望对使用 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 Scopes 部分中指定的任何标准范围。
默认范围为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/>
元素。
在 Java 中使用@Scope
Annotation 提供等效支持
使用proxyMode
属性。默认值为ScopedProxyMode.DEFAULT
哪
通常表示不应创建作用域代理,除非使用不同的默认值
已在 component-scan 指令级别进行配置。您可以指定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
method's name 作为
结果 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 别名
正如命名 Bean 中所讨论的,它是
有时需要为单个 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
annotation 中,如下例所示:
-
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()
}