从完全相同的@Configuration class 习语中注入@Beans

Injecting @Beans from within a very same @Configuration class idioms

过去我看到人们使用以下 2 个习语来注入来自相同 @Configuration 的依赖项:

@Configuration
public class MyConfiguration {

    @Bean
    public MyBeanDependencyA myBeanDependencyA(){
        return new MyBeanDependencyA();
    }

    @Bean . //IDIOM 1
    public MyBeanDependencyB1 myBeanDependencyB1(){
        return new MyBeanDependencyB1(myBeanDependencyA());
    }

    @Bean //IDIOM 2
    public MyBeanDependencyB2 myBeanDependencyB2(MyBeanDependencyA myBeanDependencyA){
        return new MyBeanDependencyB1(myBeanDependencyA);
    }
}

它们之间有什么实际区别吗?

Spring容器有那么聪明吗?

Does Spring process the whole instantiation method in each call for IDIOM 1?

不,这个叫做inter-bean dependencies,在@Configurationclass中用@Bean注解的方法会在springIOC容器中创建一个bean

The @Bean annotation is used to indicate that a method instantiates, configures and initializes a new object to be managed by the Spring IoC container. For those familiar with Spring's XML configuration the @Bean annotation plays the same role as the element. You can use @Bean annotated methods with any Spring @Component, however, they are most often used with @Configuration beans.


Does otherwise Spring inject the global managed instance when injecting for IDIOM 1?

是的,spring 如果需要在多个地方注入相同的 bean Basic concepts: @Bean and @Configuration 这种 bean 间依赖关系仅在 @Bean@Configuration 的组合中有效这也可以防止多次调用同一个 bean 方法。

Only using @Bean methods within @Configuration classes is a recommended approach of ensuring that 'full' mode is always used. This will prevent the same @Bean method from accidentally being invoked multiple times and helps to reduce subtle bugs that can be hard to track down when operating in 'lite' mode.

Does Spring process the whole instantiation method in each call for IDIOM 1? (relevant if method has any side-effect, might be not idempotent)?

默认情况下 @Configuration classes 在运行时被代理,因此 MyBeanDependencyA 将被创建一次并且 myBeanDependencyA() 将仅被 Spring 调用一次下一个调用将被代理到 return 相同的实例(就您共享的示例而言)。因为它的范围是 Singleton.

,上下文中只有一个这个 bean 的实例

Does otherwise Spring inject the global managed instance when injecting for IDIOM 1? (relevant If some external process changes the state of the original singleton bean)

IOC 容器在被查询时将 return 相同的 Singleton bean 实例。因为它是一个 Singleton 对此 bean 的所有更改(如果它是可变的)将对引用它的组件可见。


作为旁注,您可以通过使用 :

Spring 5.2 禁用配置 class 的自动代理
@Configuration(proxyBeanMethods = false)

这将阻止对从其他 @Bean 方法调用的带有 @Bean 注释的方法的代理调用。