Spring Bean Scopes – Singleton vs Prototype

When creating bean definitions you cannot only control various dependencies and configurations, but also define the scope of the bean. These scopes are configured via configuration which makes them very powerfull and flexible. You don’t need to hard code them at Java Class level. There are multiple scopes. Singleton and prototype are supported out of the box. The other scopes require a web-aware ApplicationContext. Here is a list of the scopes available:

  • singleton (Default) Single bean definition for a single object instance per container.
  • prototype Single bean definition for multiple instances.
  • request Single bean definition for a single HTTP request.
  • session Single bean definition for the HTTP session.
  • global-session Single bean definition for the global HTTP session. Typically only valid when used in portlet context.
  • application Single bean definition for the entire application bound to the lifecycle of a ServletContext

Request, session and application are only valid in the context of a web-aware ApplicationContext

Singleton Bean Scope Example

The default scope is singleton. Which means that only one instance of bean is created for a spring container. Singleton scoped beans are mostly used for stateless beans.

package com.memorynotfound.spring.core.scope;

public class CoffeeMachine {

    private long serialNr;

    public long getSerialNr() {
        return serialNr;
    }

    public void setSerialNr(long serialNr) {
        this.serialNr = serialNr;
    }
}

Configure spring bean as singleton.

// default scope is singleton
<bean class="com.memorynotfound.spring.core.scope.CoffeeMachine"/>

// explicit singleton is equivalent
<bean class="com.memorynotfound.spring.core.scope.CoffeeMachine" scope="singleton"/>

We retrieve the singleton Coffee bean and assign a value. The subsequent requests for the same bean will return the same instance of the bean.

package com.memorynotfound.spring.core.scope;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Run {

    public static void main(String... args) throws InterruptedException {
        ApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");

        Coffee coffee = context.getBean(Coffee.class);
        coffee.setBrand("Java");
        System.out.println("Coffee brand: " + coffee.getBrand());

        coffee = context.getBean(Coffee.class);
        System.out.println("Coffee brand: " + coffee.getBrand());
    }
}

Output

Serial nr: 12356789
Serial nr: 12356789

Prototype Bean Scope Example

The prototype scope means that a single bean definition is used to create multiple instances. This results in the creation of a new bean instance every time a request for that bean is made. Prototype scoped beans are mostly used for stateful beans.

package com.memorynotfound.spring.core.scope;

public class Coffee {

    private String brand;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}

Configuring prototype scoped bean.

<bean class="com.memorynotfound.spring.core.scope.Coffee" scope="prototype"/>

Everytime we get the prototype scoped bean via getBean() method of the ApplicationContext the container creates a new instance for that bean. Which means any subsequent request will also create a new bean.

package com.memorynotfound.spring.core.scope;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Run {

    public static void main(String... args) throws InterruptedException {
        ApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");

        Coffee coffee = context.getBean(Coffee.class);
        coffee.setBrand("Java");
        System.out.println("Coffee brand: " + coffee.getBrand());

        coffee = context.getBean(Coffee.class);
        System.out.println("Coffee brand: " + coffee.getBrand());
    }
}

Output

Coffee brand: Java
Coffee brand: null

Configure Beans scope with @Scope Annotation

Instead of defining your bean scope in xml, you can also annotate your bean using the @Scope annotation. This annotation takes a name parameter indicating which bean scope to use.

package com.memorynotfound.spring.core.scope;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class Coffee {

    private String brand;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}

We can use this annotation by enabling the <context:component-scan/> element. This enables annotation configuration and scans for beans in a particular package.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.memorynotfound"/>

</beans>

References

Download

You may also like...