Spring Bean Scopes
Tags: learning, springboot, spring
Published: 2024-05-26 23:38:38

Bean scope in Spring Framework refers to the <u>lifecycle of a Spring bean and its visibility in the context of the application.</u>
When you create a bean definition, you create a recipe for creating actual instances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe.

Spring provides multiple scope to register and configure beans and scoping has an impact on a state management of the component.
Singleton is the default scope of a bean, which means one instance per application context.

Bean Scopes provided by Spring:

1. **Singleton**  Only one instance of a bean is created and all request of that bean will receive the same instance. This is useful for beans that do not hold state or where the same state is to be shared by all users or threads. For example, a database connection pool 

```
@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName("org.postgresql.Driver");
        config.setJdbcUrl("jdbc:postgresql://localhost:5432/yourdatabase");
        config.setUsername("yourusername");
        config.setPassword("yourpassword");
        config.setMaximumPoolSize(10);
        config.setMinimumIdle(2);
        config.setPoolName("HikariCP");

        return new HikariDataSource(config);
    }
}
```

2. **Prototype**  A new instance is being created each time a bean is requested from the container. Useful for stateful beans or beans that are not thread-safe, such as a bean that maintains user-specific data during an operation.

```
@Component
@Scope("prototype")
public class UserData {

    private String username;
    private String operation;

    // Getters and setters
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getOperation() {
        return operation;
    }

    public void setOperation(String operation) {
        this.operation = operation;
    }
}
```

3. **Request** This scope is Only valid in the context of a web-aware Spring ApplicationContext for a single http request. A new bean is created for each http request. For example, a bean that tracks the progress of a user's request or data specific to that request, such as user credentials or input parameters.

```
@Component
@RequestScope
public class RequestData {

    private String userId;
    private String requestStatus;

    // Getters and setters
    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getRequestStatus() {
        return requestStatus;
    }

    public void setRequestStatus(String requestStatus) {
        this.requestStatus = requestStatus;
    }
}
```

4. **Session** A new bean is created for each http session by the container. Also applicable in web-aware Spring ApplicationContext. Useful for user sessions in a web application, like storing a user's authenticated session or a shopping cart in an e-commerce site.

```
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {
    private String username; // You can add more session-related data here

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}
```

5. **Application** Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext. For example, application-wide configuration that is web-context aware, like a cache that is shared across sessions but not across different applications.


6. **WebSocket** Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

The scope of a bean affects its injection into another bean in terms of lifecycle management and statefulness:

**Singleton beans** injected into other beans will have their state shared across the entire application, making them suitable for shared configurations or stateless services.

**Prototype-scoped beans** ensure that a new instance is provided each time a bean is injected, suitable for stateful beans or beans that are not thread-safe.

**Request, Session, Application, and Websocket scopes** allow beans to be tied to the lifecycle of web components, making them ideal for managing user sessions, application context, and real-time communication channels respectively.

**Singleton Beans with Prototype-bean Dependencies**
When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus, if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.

**Custom Scopes**
The bean scoping mechanism is extensible. You can define your own scopes or even redefine existing scopes, although the latter is considered bad practice and you cannot override the built-in singleton and prototype scopes.