Java Spring - Using @Scope Annotation to Set a POJO's Scope
Last Updated :
17 Dec, 2025
In the Spring Framework, each bean defined in the IoC container has a scope that determines its lifecycle and how many instances are created. By default, Spring creates only one instance of a bean (singleton scope), but it also supports other scopes that control how and when new bean instances are generated.
The @Scope annotation is used to define this behavior at either the class level (for components) or method level (for @Bean methods).
Bean Scopes in Spring
- singleton: Creates a single bean instance per Spring IoC container.
- prototype: Creates a new bean instance every time it is requested.
- request: Creates one bean instance per HTTP request (used in web applications).
- session: Creates one bean instance per HTTP session (used in web applications).
@Scope Annotation
The @Scope annotation defines the lifecycle scope of a bean. By default, every Spring bean is singleton, meaning the same instance is shared across the container.
Syntax
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
String value() default "singleton";
}
Usage
- When used with @Component, it applies to all instances of that class.
- When used with @Bean, it applies to the specific bean returned by the method.
Example: Demonstrating Bean Scope
We’ll create a simple shopping application to demonstrate how singleton and prototype scopes work.
Project Structure:
Project Structure
Java
package com.geeksforgeeks.shop;
import java.util.*;
import org.springframework.stereotype.Component;
@Component
public class ShoppingList {
private List<Device> items = new ArrayList<>();
public void addItem(Device item) {
items.add(item);
}
public List<Device> getItems() {
return items;
}
}
Since we didn’t specify any scope, Spring treats this bean as a singleton.
Step 2: Create Device Class
Java
package com.geeksforgeeks.shop;
public class Device {
private String name;
private double price;
public Device() {}
public Device(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() { return name; }
public double getPrice() { return price; }
public void setName(String name) { this.name = name; }
public void setPrice(double price) { this.price = price; }
public String toString() { return name + " " + price; }
}
This is a simple POJO representing a product with basic attributes.
Step 3: Create Product Classes
Laptop.java
Java
package com.geeksforgeeks.shop;
public class Laptop extends Device {
private boolean touchScreen;
public boolean isTouchScreen() { return touchScreen; }
public void setTouchScreen(boolean touchScreen) {
this.touchScreen = touchScreen;
}
}
Mobile.java:
Java
package com.geeksforgeeks.shop;
public class Mobile extends Device {
private int batteryCapacity;
public int getBatteryCapacity() { return batteryCapacity; }
public void setBatteryCapacity(int capacity) {
this.batteryCapacity = capacity;
}
}
Both classes extend Device and add specific attributes to represent product types.
Java
package com.geeksforgeeks.shop.config;
import org.springframework.context.annotation.*;
import com.geeksforgeeks.shop.*;
@Configuration
@ComponentScan("com.geeksforgeeks.shop")
public class ShoppingListConfig {
@Bean
public Device lenovo() {
Laptop d1 = new Laptop();
d1.setName("LENOVO");
d1.setPrice(65000);
d1.setTouchScreen(true);
return d1;
}
@Bean
public Device dell() {
Laptop d2 = new Laptop();
d2.setName("DELL");
d2.setPrice(57000);
return d2;
}
@Bean
public Device moto() {
Mobile d3 = new Mobile();
d3.setName("MOTOROLA");
d3.setPrice(40000);
d3.setBatteryCapacity(4000);
return d3;
}
@Bean
public Device iq() {
Mobile d4 = new Mobile();
d4.setName("iQOO");
d4.setPrice(55000);
d4.setBatteryCapacity(4700);
return d4;
}
}
This configuration file declares Device beans and enables component scanning for @Component classes.
Step 5: Testing the Application
Java
package com.geeksforgeeks.shop;
import org.springframework.context.*;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.geeksforgeeks.shop.config.ShoppingListConfig;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ShoppingListConfig.class);
Device lenovo = context.getBean("lenovo", Device.class);
Device dell = context.getBean("dell", Device.class);
Device moto = context.getBean("moto", Device.class);
Device iq = context.getBean("iq", Device.class);
ShoppingList list1 = context.getBean(ShoppingList.class);
list1.addItem(lenovo);
list1.addItem(moto);
System.out.println("List 1: " + list1.getItems());
ShoppingList list2 = context.getBean(ShoppingList.class);
list2.addItem(dell);
System.out.println("List 2: " + list2.getItems());
ShoppingList list3 = context.getBean(ShoppingList.class);
list3.addItem(iq);
System.out.println("List 3: " + list3.getItems());
}
}
Here, each call to context.getBean(ShoppingList.class) fetches the same bean instance because the default scope is singleton.
Output (Singleton Scope):
OutputAll lists share the same instance, showing singleton behavior.
Changing Scope to prototype
To create a new instance each time, annotate the bean with @Scope("prototype").
Updated ShoppingList.java:
Java
package com.geeksforgeeks.shop;
import java.util.*;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class ShoppingList {
private List<Device> items = new ArrayList<>();
public void addItem(Device item) {
items.add(item);
}
public List<Device> getItems() {
return items;
}
}
Now, each getBean() call creates a separate instance.
Output (Prototype Scope):
Now if we rerun the Main.java class, we can see the three different shopping lists. The output will be as follows.
OutputEach shopping list is now independent.
Explore
Java Enterprise Edition
Multithreading
Concurrency
JDBC (Java Database Connectivity)
Java Frameworks
JUnit