按需实例化Spring Bean,而不是在启动时实例化

时间:2019-10-10 18:00:53

标签: java spring spring-boot dependency-injection

Spring Boot 2.x在这里。我目前在@Configuration类中定义了一堆bean,如下所示:

@Configuration
public class SomeConfig {

    @Bean
    public Fizz fizz() { ... }

    @Bean
    public Buzz buzz() { ... }

}

通常,Spring将启动此类并在 startup 处实例化那些bean。但是,在我的情况下,我希望Spring在启动时 skip 加载此类(并实例化bean),而不是通过编程/按需执行,就像这样:

public void processRequest(SomeRequest request) {

    Fizz fizz = SpringAdhocLoader.load(SomeConfig.class, Fizz.class);
    Buzz buzz = SpringAdhocLoader.load(SomeConfig.class, Buzz.class);

    // use these two beans in this method somehow

}

我有一个非常具体的原因需要这样做,这超出了此问题的范围。因此,我将真的感谢以下回答:“ 是可以做到的,这是... 的方式”或“ 不能用春天,这就是为什么... “,而不是的答案/评论,问我为什么我要这样做。相信我,我需要!

在一天结束时,我正在寻找一种方法来告诉Spring not 实例化我的SomeConfig类中的所有bean,直到我的代码的另一部分明确想要它们为止创建。这可能吗?如果可以,怎么办?


更新

如果Fizz看起来像这样:

@Component
public class Foobar {
    ...
}

public class Fizz {

    @Autowired
    private Foobar foobar;

    ...
}

@Lazy上的SomeConfig注释是否会在实例化Fizz时避开,即使其自动装配/注入了@Component依赖项? / p>

1 个答案:

答案 0 :(得分:1)

根据您的确切要求,有多种方法可以实现此目的:

  • 如果每个人都应该使用相同的对象实例,请使用@Lazy,自动调用销毁回调,并在首次请求bean时创建对象。

  • 使用期限较短的@Scope(例如“ session”或“ request”),如果该范围内的每个人都应使用相同的对象实例,则将自动调用销毁回调,并在以下情况下创建对象它是第一个请求的。

  • 如果每个人都应该获得一个新的对象实例,请使用@Scope("prototype"),并且您愿意手动调用任何销毁回调。

在所有情况下,注入“裸” bean将请求创建该bean。您可以通过注入Provider来避免这种情况:

class Foo {
    @Inject Bar bar;  // requests the creation of bar
}

class Foo {
    @Inject Provider<Bar> barProvider; // does not cause the creation of bar

    void something() {
        Bar bar = barProvider.get(); // requests the creation of bar 
    }
}