Understanding Scopes in Spring Framework (Advanced topic)
Shant Khayalian - Balian's IT

Understanding Scopes in Spring Framework (Advanced topic)

Scopes in the Spring Framework help manage the lifecycle and visibility of beans. This means controlling how and when a bean (a Java object managed by Spring) is instantiated, how long it lives, and how it is shared within the application context. To make it simple, let's use examples from everyday life to understand why we have scopes, the need for multiple scopes despite having a default singleton scope, the problems they solve, and how to determine the scope for a bean.

1. Why Do We Have Scopes in Spring?

Scopes in Spring define the lifecycle and visibility of beans within the Spring IoC (Inversion of Control) container. Scopes manage how and when a bean is instantiated, how long it lives, and how it is shared within the application context. This allows developers to control the beans' lifecycles according to specific requirements, ensuring efficient resource management and appropriate state handling.

Real-life Example: Think of beans as different types of assistants helping you with your daily tasks. Depending on the task, you might need an assistant who is always available (singleton), one who helps you with a specific task and then leaves (prototype), one who helps you throughout the day (request), or one who assists you during a longer period, like a week (session).

2. Why Do We Have Scopes if There is a Default Singleton Scope?

The default singleton scope creates a single instance of a bean per Spring IoC container. While this is suitable for many scenarios, different components in an application might have varying lifecycle requirements that the singleton scope cannot fulfill.

Example:

  1. Prototype Scope: Needed when a new instance of a bean is required every time it is requested.
  2. Request Scope: Suitable for web applications where a new bean instance is needed for each HTTP request.
  3. Session Scope: Ideal for managing user-specific data across multiple HTTP requests within a single session.
  4. Global Session Scope: Used in Portlet-based web applications for managing user-specific data across different Portlet sessions.

Different scopes provide the necessary flexibility to manage beans according to specific lifecycle and visibility requirements.

3. Why Were Scopes Created and What Problems Do They Solve?

Scopes were created to solve several key issues in managing bean lifecycles:

  • Resource Management: Ensures efficient use of resources by creating and destroying beans as needed.
  • State Management: Maintains state consistency by ensuring beans are not improperly shared or reused.
  • Concurrency Control: Avoids issues with concurrent access to beans by providing appropriate scopes.
  • Context-specific Beans: Ensures beans are available only within specific contexts, such as a single request or session.

By defining scopes, Spring allows developers to create modular, efficient, and maintainable applications tailored to various use cases.

4. Situations and Examples of Different Scopes

To illustrate the usage of different scopes, let's consider the following simple personal life example.

Real-Life Example of Scopes Using Personal Life Scenario

Imagine you are managing your daily activities with the help of different tools: a personal assistant, an address book, and a notepad. Each of these tools has different requirements for how long they are needed and how they should be shared.

Singleton Scope

Use Case: Shared, stateless services that need to be available throughout your life.

Example: An AddressBook which provides contact information.

@Service
public class AddressBook {
    private List<Contact> contacts = new ArrayList<>();

    public List<Contact> getAllContacts() {
        // Retrieve contact list
        return contacts;
    }

    public void addContact(Contact contact) {
        contacts.add(contact);
    }
}        

Real-life Example: The address book holds contact details and is used throughout your life. Since the contact data is relatively static and shared across different activities, it makes sense to use a singleton scope to ensure there's only one instance of the address book.

Prototype Scope

Use Case: Beans that need to be instantiated multiple times, each with a unique state.

Example: A Note which represents a temporary note.

@Component
@Scope("prototype")
public class Note {
    private long id;
    private String content;

    // Getters and setters
}        

Real-life Example: Each time you write a note, a new Note object is created with its own unique content. Using the prototype scope ensures that each note is independent of others, preventing shared state issues.

Request Scope

Use Case: Beans that need to be created for each specific context or activity.

Example: A DailyTask bean that holds data specific to a day's tasks.

@Component
@Scope("request")
public class DailyTask {
    private List<Task> tasks = new ArrayList<>();

    public void addTask(Task task) {
        tasks.add(task);
    }

    public List<Task> getTasks() {
        return tasks;
    }
}        

Real-life Example: Each day, you plan tasks for the day. Using a request-like scope ensures that each day's tasks are independent of the previous day’s tasks. Although this scope is more abstract in a non-web application, it represents the idea of creating a fresh set of tasks for each new context.

Session Scope

Use Case: Beans that need to persist across multiple activities within a specific period or session.

Example: A PersonalAssistant which stores tasks and reminders that you are currently managing.

@Component
@Scope("session")
public class PersonalAssistant {
    private List<Task> tasks = new ArrayList<>();

    public void addTask(Task task) {
        tasks.add(task);
    }

    public List<Task> getTasks() {
        return tasks;
    }
}        

Real-life Example: The personal assistant manages tasks that you are currently working on. These tasks need to persist as you go about your day. Using a session scope ensures that tasks remain accessible throughout the session (e.g., the day or a specific project).

Determining the Scope for Address in Student Example

Classes:

public class Student {
    private long id;
    private String name;
    private Address address;
    // Other student details
}

public class Address {
    private long id;
    private String address;
    // Other address details
}        

Scope for Address:

Singleton Scope: If the Address instance is shared across all students and doesn't change, it can be singleton scoped.

@Service
public class AddressService {
    private final Address address = new Address();

    public Address getAddress() {
        return address;
    }
}        

Prototype Scope: If each Student needs a unique Address instance, it can be prototype scoped.

@Component
@Scope("prototype")
public class Address {
    private long id;
    private String address;

    // Getters and setters
}        

Real-life Example: In a personal context, think of Address as the home address of a friend. Each friend (or Student) has a unique address. By using prototype scope, each Student gets a unique Address instance, ensuring that addresses are not shared between friends.


Can I Create My Own Scope?

Yes, you can create your own custom scope in Spring. This is useful when you need a specific lifecycle management that is not covered by the existing scopes.

Steps to Create a Custom Scope:

  1. Implement the Scope Interface: Create a class that implements the org.springframework.beans.factory.config.Scope interface.

public class CustomThreadScope implements Scope {

    private final ThreadLocal<Map<String, Object>> threadScope = ThreadLocal.withInitial(HashMap::new);

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        Map<String, Object> scope = threadScope.get();
        return scope.computeIfAbsent(name, k -> objectFactory.getObject());
    }

    @Override
    public Object remove(String name) {
        Map<String, Object> scope = threadScope.get();
        return scope.remove(name);
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
        // Not required for this example
    }

    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }

    @Override
    public String getConversationId() {
        return Thread.currentThread().getName();
    }
}        

Register the Custom Scope: Use a CustomScopeConfigurer to register the custom scope.

@Configuration
public class CustomScopeConfig {

    @Bean
    public static CustomScopeConfigurer customScopeConfigurer() {
        CustomScopeConfigurer configurer = new CustomScopeConfigurer();
        configurer.addScope("thread", new CustomThreadScope());
        return configurer;
    }
}        

Use the Custom Scope: Annotate your beans with the custom scope.

@Component
@Scope("thread")
public class ThreadScopedBean {
    // Thread scoped bean logic
}        

What is Under the Annotation @Scope and How It Works

The @Scope annotation in Spring is used to specify the scope of a bean. It can be applied at the class level in conjunction with the @Component or @Bean annotations.

Example:

@Component
@Scope("prototype")
public class ExampleBean {
    // Bean logic
}        

How It Works:

  • Annotation Processor: When Spring processes the @Scope annotation, it uses the scope name to determine the lifecycle and visibility rules for the bean.
  • Bean Definition: Spring creates a BeanDefinition for the annotated bean, which includes the scope information.
  • Scope Implementation: During bean creation, Spring uses the scope's implementation to manage the bean's lifecycle


Scopes in Spring are essential for managing the lifecycle and visibility of beans, ensuring efficient resource management, state consistency, and appropriate concurrency control. By understanding and utilizing different scopes, developers can tailor bean lifecycles to the specific requirements of their applications, leading to more robust and maintainable systems. The provided simple personal life examples illustrate how different scopes can be applied to manage the lifecycle of beans effectively.

Test your Knowledge:

1. Why Do We Have Scopes in Spring?

Test Question: What do scopes in Spring define and manage?

A) The appearance of beans within the application context

B) The lifecycle and visibility of beans

C) The programming language used for bean instantiation

D) The version control of beans

2. Why Do We Have Scopes if There is a Default Singleton Scope?

Test Question: What does the default singleton scope create?

A) A new instance of a bean per request

B) Multiple instances of a bean per session

C) A single instance of a bean per Spring IoC container

D) Dynamic instances of a bean per application context

3. Why Were Scopes Created and What Problems Do They Solve?

Test Question: What key issues do scopes in Spring solve?

A) Database connectivity and error handling

B) Resource management, state management, and concurrency control

C) Front-end design and user interface responsiveness

D) Backend server optimization and load balancing

4. Situations and Examples of Different Scopes?

Test Question: Which scope is suitable for beans that need to persist across multiple activities within a specific session?

A) Singleton Scope

B) Prototype Scope

C) Request Scope

D) Session Scope


Find us

linkedin Shant Khayalian

Facebook Balian’s

X-platform Balian’s

web Balian’s

#SpringFramework #JavaDevelopment #BeanScopes #SoftwareArchitecture #DeveloperTips #SpringIoC #JavaProgramming #SoftwareDevelopment #BackendDevelopment

要查看或添加评论,请登录

Shant Khayalian的更多文章

社区洞察

其他会员也浏览了