Understanding Scopes in Spring Framework (Advanced topic)
Shant Khayalian
Co-Founder & Managing Director @ Balian's Technologies | Developing Smart Solutions from Hardware to Software | AI-Driven Management Systems & Cutting-Edge Technologies
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:
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:
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:
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:
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