Spring @Bean方法可以返回实例字段吗?

时间:2019-05-31 07:29:25

标签: java spring

以下Spring bean声明似乎可以按预期运行并运行:

@Configuration
public class AppConfig {

    private final Foo foo;

    public AppConfig() {
        foo = new Foo();
    }

    @Bean
    public Foo foo() {
        return foo;
    }
}

其中“符合预期”是指“ 显然没有任何问题”。

假设Foo有一些复杂的生命周期(例如,使用AutoCloseable管理外部资源),这是foo()的有效且明智的声明吗?我可以找到的所有示例(无论正式与否)都表明foo实例应在foo()内部实例化,而不是存储在字段中或从字段中检索。但是,我在任何文档中都找不到确切的信息,这应该或不应该保证安全。

我能找到的最相关的文档是关于Spring IoC bean生命周期的,例如https://docs.spring.io/spring/docs/5.1.0.RELEASE/spring-framework-reference/core.html#beans-factory-scopes。例如,在行之间读取singletonapplication范围内的Bean将是有效的,因为到停止时,该应用程序将不再有效。由于singleton是默认范围,因此上面的声明将隐式有效。

即使您具有适当的作用域,也要假设您引入了另一种针对特定配置文件的声明

@Bean("foo")
@Profile("!test")
public Foo realFoo() {
    return this.foo;
}

@Bean("foo")
@Profile("test")
public Foo testFoo() {
    return new TestFoo();
}

即使激活this.foo配置文件时,test仍将始终实例化吗?如果是这样,即使该bean应该处于非活动状态,Spring仍然管理realFoo()的值吗?

此问题不是Spring @Bean at method returning already created bean的重复,{em}就是这个问题,但是该问题可以正确识别答案。

1 个答案:

答案 0 :(得分:2)

如果将IoC存储在现场,您将失去Spring IoC所提供的好处,甚至可能导致某些范围的意外行为。

如果范围是singletonapplication,这将起作用,因为它将仅调用一次foo()。但是,如果范围更改为protoptype(每次都创建一个新实例)。然后可能导致意外行为。因为您将foo存储在一个字段中,所以它仍将像singleton一样工作,因为它始终指向同一实例。

如果您在构造函数中初始化类,则即使配置文件未处于活动状态,它也将始终初始化。 Spring无法(也不应该)检测实例的启动位置。如果配置文件未激活,Spring IoC将不会调用该方法。除了上面的解释之外,在方法本身中初始化实例将更加安全。