Spring Bean Scope

What is Bean Scope in Spring?

In the Spring Framework, a bean scope defines the lifecycle of a bean (i.e., how many instances of a bean should be created and how Spring manages them). The scope dictates whether a new instance of a bean should be created with each request, or if the same instance should be shared across multiple requests.


Types of Bean Scopes


1. Singleton Bean Scope

The singleton scope is the default bean scope in Spring. It ensures that only one instance of the bean is created and is shared across all requests.


Race Condition in Singleton Beans

A race condition occurs when two or more threads access shared data and try to change it simultaneously. In the case of a singleton bean, multiple threads could access the same bean instance, leading to inconsistent data if not properly synchronized.

To prevent race conditions, you can use techniques such as:


Use Case of Singleton Scope

Singleton beans are useful when you want to share data or configuration across multiple components in your application.

For example, a logging service can be implemented as a singleton bean, since it doesn't require multiple instances for different parts of the application.

Example Code: Singleton Bean in Spring

        import org.springframework.context.annotation.Scope;
        import org.springframework.stereotype.Service;
        
        @Service
        @Scope("singleton")  // By default, it's singleton, but we explicitly define it here
        public class LoggingService {
            public void log(String message) {
                System.out.println("Logging message: " + message);
            }
        }
            

Eager vs Lazy Instantiation of Singleton Scope

Eager Instantiation (Default Behavior)
Use Case of Eager Instantiation

Eager instantiation is ideal for beans that are crucial to the application’s startup process, such as configuration services or connection pools, which need to be ready as soon as the application starts.

Example Code: Eager Instantiation

        import org.springframework.context.annotation.Scope;
        import org.springframework.stereotype.Service;
        
        @Service
        @Scope("singleton")  // Eager instantiation, created at application startup
        public class ConfigurationService {
            public ConfigurationService() {
                System.out.println("ConfigurationService bean created at startup");
            }
        }
            

Lazy Instantiation
Use Case of Lazy Instantiation

Lazy instantiation is useful for beans that are not always needed during the lifecycle of the application, such as optional services or background tasks.

Example Code: Lazy Instantiation

        import org.springframework.context.annotation.Lazy;
        import org.springframework.stereotype.Service;
        
        @Service
        @Lazy  // Bean will be instantiated only when needed
        public class ReportService {
            public ReportService() {
                System.out.println("ReportService bean created on-demand");
            }
        }
            
Singleton Scope

2. Prototype

Singleton Scope

3. Request/Session/Application Scopes

Singleton Scope

Interview Questions and Answers

What is the Singleton Scope in Spring, and how does it work?

  • In Spring, the singleton scope is the default bean scope, meaning that the Spring IoC (Inversion of Control) container creates a single instance of the bean per Spring context. This instance is shared across all other components that require this bean, providing the same object each time it’s requested.
  • Follow-up: How is this different from the Singleton Design Pattern?
    • While both create a single instance, in the Singleton Design Pattern, the control of the instance creation is within the class itself, while in Spring, the container (IoC) manages the bean lifecycle.

How does Spring ensure that the Singleton beans are thread-safe?

  • Spring does not make Singleton beans thread-safe by default. The developer needs to handle thread safety manually by using techniques such as synchronization, using immutable objects, or relying on thread-safe classes like ConcurrentHashMap.

What happens if a Singleton bean holds state in a multi-threaded environment?

  • Since a Singleton bean is shared across the entire application, if it holds mutable state, and multiple threads access it simultaneously, it could lead to race conditions or inconsistent data. It is important to either avoid holding mutable state or implement synchronization mechanisms to prevent concurrency issues.

Can Singleton beans be garbage collected?

  • Yes, Singleton beans can be garbage collected, but only when the Spring container itself is garbage collected or shut down. Until then, the singleton bean will persist for the entire lifecycle of the application context.

Scenario: You have a Singleton bean that handles configuration settings in your application. However, some threads are seeing stale data after an update to the configuration. What could be the issue?

  • This could be happening due to the absence of proper synchronization in a multi-threaded environment. Since the Singleton bean is shared across threads, updates to the configuration might not be visible to all threads due to caching or lack of synchronization. The solution could be:
    Ensuring proper synchronization (e.g., using the volatile keyword or synchronized methods).
    Using atomic variables or thread-safe collections for configuration management.

You have a Singleton service bean that requires a resource-heavy initialization process. The application has a slow startup due to this. What approach would you take to solve this?

In this scenario, lazy initialization is a good solution. By annotating the Singleton bean with @Lazy, I can delay its initialization until it is actually required by the application, reducing the initial startup time.


                @Service
                @Lazy
                public class HeavyResourceService {
                    public HeavyResourceService() {
                        // Heavy initialization logic
                    }
                }
                
How would you manage Singleton beans in a microservices architecture where each microservice may require its own instance?

In a microservices architecture, each microservice typically has its own isolated application context, so each microservice will have its own Singleton bean instance, independent of other services. If a microservice needs multiple instances of the same bean, I would use prototype scope or a different context strategy, but typically the Singleton scope per microservice context works well.

You have a Singleton bean in a high-traffic application, and it is becoming a performance bottleneck. How would you approach solving this?

In this scenario, the Singleton bean could be becoming a bottleneck due to resource contention. To resolve this, I would:

  • Check if the Singleton bean is stateless. If so, it should perform well in high-traffic environments.
  • If the bean is stateful, I could refactor it to be stateless or switch it to prototype scope to avoid shared state issues.
  • Use caching or asynchronous processing to reduce the load on the Singleton bean.
How does Spring handle Singleton beans in a distributed environment?

In a distributed environment (e.g., multiple instances of an application running on different nodes), each Spring container will maintain its own Singleton bean instance. Therefore, Singleton beans are scoped to the application context, not the entire distributed system. If you need a shared instance across nodes, you would need to implement a centralized cache or use a distributed service.