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

Whi*_*cal 6 java spring ioc-container inversion-of-control spring-boot

在过去,我见过人们使用以下两个惯用法从同一个对象中注入依赖项@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • Spring会在每次对IDIOM 1的调用中处理整个实例化方法吗?(有关方法是否有副作用,可能不是幂等的)?
  • 注入IDIOM 1时,Spring是否还会注入全局托管实例?(与某些外部进程更改原始单例Bean的状态有关)

Spring容器这么聪明吗?

Dea*_*ool 5

Spring会在每次对IDIOM 1的调用中处理整个实例化方法吗?

不,这称为Bean间依赖关系,该方法@Bean@Configuration类中使用注释进行注释, 将在spring IOC容器中创建一个bean

@Bean批注用于指示方法实例化,配置和初始化要由Spring IoC容器管理的新对象。对于那些熟悉Spring XML配置的人来说,@ Bean注释与元素扮演着相同的角色。您可以将@Bean批注方法与任何Spring @Component一起使用,但是,它们通常与@Configuration bean一起使用。


注入IDIOM 1时,Spring是否还会注入全局托管实例?

是的,如果需要在多个位置使用spring注入相同的bean,则基本概念:@Bean和@Configuration此bean之间的依赖关系只能与结合使用,@Bean并且@Configuration还可以防止多次调用相同的bean方法。

建议仅在@Configuration类中使用@Bean方法,以确保始终使用“完全”模式。这将防止相同的@Bean方法被意外调用多次,并有助于减少在“精简”模式下运行时难以追查的细微错误。


mic*_*alk 5

Spring会在每次对IDIOM 1的调用中处理整个实例化方法吗?(有关方法是否有副作用,可能不是幂等的)?

默认情况下,@Configuration类在运行时进行代理,因此类MyBeanDependencyA将被创建一次,并且myBeanDependencyA()仅由Spring调用一次,并且将对下一次调用进行代理以返回相同的实例(就您共享的示例而言)。由于上下文的范围为,因此在该上下文中只有该bean的一个实例Singleton


注入IDIOM 1时,Spring是否还会注入全局托管实例?(与某些外部进程更改原始单例Bean的状态有关)

询问时,IOC容器将返回相同的Singleton bean实例。由于它是Singleton所有,因此对该bean 的所有更改(如果它是可变的)对于引用该bean的组件都是可见的。


顺便说一句,从Spring 5.2开始,您不能通过使用以下命令禁用配置类的自动代理:

@Configuration(proxyBeanMethods = false)
Run Code Online (Sandbox Code Playgroud)

这样可以防止代理对@Bean其他@Bean方法调用的方法的调用。