springspring-beanspring-ioc

Is a spring bean created with NEW really a singleton


I created a spring bean in a configuration class like this:

@Bean
MyClass getMyClass() {
    MyClass mc = new MyClass()
    return mc;
}

Whenever MyClass is autowired in another class that needs it injected, will it always create a new object by virtue of new in bean definition? Is a bean created this way a real singleton ?


Solution

  • Spring guarantees that whatever you do in the method annotated with Bean annotation it will be done only once. Internal Spring factories will take care about that.

    Of course it depends from scope but by default scope is singleton. See docs:

    1. Scopes
    2. Bean
    3. Is spring default scope singleton or not?

    Small example which should help you to understand how it works:

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.time.LocalDateTime;
    import java.util.Random;
    
    @Configuration
    public class SpringApp {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringApp.class);
    
            System.out.println(ctx.getBean(MyClass.class));
            System.out.println(ctx.getBean(MyClass.class));
            System.out.println(ctx.getBean(MyClass.class));
            System.out.println(ctx.getBean(MyClass.class));
        }
    
        @Bean
        public MyClass getMyClass() {
            System.out.println("Create instance of MyClass at " + LocalDateTime.now());
            MyClass myClass = new MyClass();
    
            return myClass;
        }
    }
    
    class MyClass {
    
        private int value = new Random().nextInt();
    
        @Override
        public String toString() {
            return super.toString() + " with values = " + value;
        }
    }
    

    prints:

    Create instance of MyClass at 2019-01-09T22:54:37.025
    com.celoxity.spring.MyClass@32a068d1 with values = -1518464221
    com.celoxity.spring.MyClass@32a068d1 with values = -1518464221
    com.celoxity.spring.MyClass@32a068d1 with values = -1518464221
    com.celoxity.spring.MyClass@32a068d1 with values = -1518464221
    

    When you define bean with scope protoype

    @Scope("prototype")
    @Bean
    public MyClass getMyClass()
    

    App prints:

    Create instance of MyClass at 2019-01-09T22:57:12.585
    com.celoxity.spring.MyClass@282003e1 with values = -677868705
    Create instance of MyClass at 2019-01-09T22:57:12.587
    com.celoxity.spring.MyClass@7fad8c79 with values = 18948996
    Create instance of MyClass at 2019-01-09T22:57:12.587
    com.celoxity.spring.MyClass@71a794e5 with values = 358780038
    Create instance of MyClass at 2019-01-09T22:57:12.587
    com.celoxity.spring.MyClass@76329302 with values = 868257220