Search code examples
javaspringspring-bootinversion-of-controlioc-container

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


In the past I have seen people using the following 2 idioms to inject dependencies from the same @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);
    }
}

Is there any practical difference between them?

  • Does Spring process the whole instantiation method in each call for IDIOM 1? (relevant if method has any side-effect, might be not idempotent)?
  • 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)

Is Spring container that smart?


Solution

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

    By default @Configuration classes are proxied at runtime so the MyBeanDependencyA will be created once and myBeanDependencyA() will be called only once by Spring and next calls will be proxied to return the same instance (as far as example that you shared is concerned). There will be only one instance of this bean in the context as it's scope is Singleton.


    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)

    The IOC container will return same instance of Singleton bean when it is queried to do so. Since it is a Singleton all changes to this bean (if it is mutable) will be visible to components that have reference to it.


    As a side note you can disable autoproxing of configuration class since Spring 5.2 by using :

    @Configuration(proxyBeanMethods = false)
    

    which will prevent proxying calls of methods annotated with @Bean invoked from other @Bean methods.