If a bean is defined with singleton scope, there will only be one single object instance initialized in the Spring container. All requests to this bean will return the same shared instance. This is the default scope when defining a bean.
Given the following MyBean class:
public class MyBean {
private static final Logger LOGGER = LoggerFactory.getLogger(MyBean.class);
private String property;
public MyBean(String property) {
this.property = property;
LOGGER.info("Initializing {} bean...", property);
}
public String getProperty() {
return this.property;
}
public void setProperty(String property) {
this.property = property;
}
}
We can define a singleton bean with the @Bean annotation:
@Configuration
public class SingletonConfiguration {
@Bean
public MyBean singletonBean() {
return new MyBean("singleton");
}
}
The following example retrieves the same bean twice from the Spring context:
MyBean singletonBean1 = context.getBean("singletonBean", MyBean.class);
singletonBean1.setProperty("changed property");
MyBean singletonBean2 = context.getBean("singletonBean", MyBean.class);
When logging the singletonBean2 property, the message "changed property" will be shown, since we just retrieved the same shared instance.
Since the instance is shared among different components, it is recommended to define singleton scope for stateless objects.
By default, singleton beans are pre-instantiated. Hence, the shared object instance will be created when the Spring container is created. If we start the application, the "Initializing singleton bean..." message will be shown.
If we don't want the bean to be pre-instantiated, we can add the @Lazy annotation to the bean definition. This will prevent the bean from being created until it is first requested.
@Bean
@Lazy
public MyBean lazySingletonBean() {
return new MyBean("lazy singleton");
}
Now, if we start the Spring container, no "Initializing lazy singleton bean..." message will appear. The bean won't be created until it is requested for the first time:
logger.info("Retrieving lazy singleton bean...");
context.getBean("lazySingletonBean");
If we run the application with both singleton and lazy singleton beans defined, It will produce the following messages:
Initializing singleton bean...
Retrieving lazy singleton bean...
Initializing lazy singleton bean...