Java Spring Using @Scope Annotation to Set a POJO's Scope (original) (raw)

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

@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

Example: Demonstrating Bean Scope

We’ll create a simple shopping application to demonstrate how singleton and prototype scopes work.

Project Structure:

ProjectStructure

Project Structure

Step 1: Define ShoppingList Bean (Default Singleton Scope)

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.

Step 4: Configure Bean Definitions

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):

Output

Output

All 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.

Output

Each shopping list is now independent.