Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Singleton scope vs application scope

What is the difference between the singleton and application spring scopes ?

I know that the singleton scope creates one instance per application and the application scope is working in the same way, then what is the main difference ?

I need an example to shows me the difference.

like image 860
S. Najim Avatar asked Apr 13 '18 14:04

S. Najim


People also ask

What is the difference between singleton and prototype scope in Spring?

Singleton: means single bean definition to a single object instance per Spring IOC container. Prototype: means a single bean definition to any number of object instances.

What are the different types of scopes in Spring?

The Spring Framework supports the following five scopes, three of which are available only if you use a web-aware ApplicationContext. Sr.No. This scopes the bean definition to a single instance per Spring IoC container (default). This scopes a single bean definition to have any number of object instances.

What is singleton scope in Spring?

The scope of the Spring singleton is best described as per container and per bean. This means that if you define one bean for a particular class in a single Spring container, then the Spring container will create one and only one instance of the class defined by that bean definition.

What is application scope in Spring?

In the application scope, Spring creates a bean instance per web application runtime. It is similar to singleton scope, with one major difference. Singleton scoped bean is singleton per ApplicationContext where application scoped bean is singleton per ServletContext.


2 Answers

To understand the difference between application scope and singleton scope you need to understand what ServletContext and ApplicationContext are.

A ServletContext is shared between all servlets living on the same servlet container (e.g. Tomcat). This is a Java EE class (it belongs to the package javax.servlet). Beans annotated with @ApplicationScope are bounded to the ServletContext.

An ApplicationContext represents a Spring IoC container, so it is a Spring-specific class (it belongs to the package org.springframework.context). Singleton scoped beans are bounded to the ApplicationContext.

You can have multiple IoC container in the same servlet container, so you can have multiple singleton beans of the same type but only one application scoped bean of each type.

I provide an example using Spring Boot and Spring MVC.

We need to introduce also the DispatcherServlet. The DispatcherServlet receives HTTP requests and forwards them to the appropriate controller. An ApplicationContext is associated to each DispatcherServlet. It is possible to configure Spring to create multiple DispatcherServlets and associate a different ApplicationContext to each of them.

Notice that in a standard configuration there is only one DispatcherServlet, so it is usually not possible to distinguish a singleton scoped bean from an application scoped bean. I would also like to point out that I see no practical use for the custom configuration I'm going to show you, other than to provide a concrete example of the difference between these two scopes.

The following diagram shows the relations between all the elements of the example:

Example of multiple singleton scoped bean

Let's look at the code. Please, pay attention to the package names!

In the package com.example.demo.beans we create the 2 beans. A random number is generated during beans initialization, so that we can distinguish them.

@ApplicationScope
@Component
public class MyApplicationScopeBean {

    private final double id = Math.random();

    public double getId() {
        return id;
    }
}
// Singleton is the default scope
@Component
public class MySingletonBean {

    private final double id = Math.random();

    public double getId() {
        return id;
    }
}

The startup class is put in com.example.demo:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        // The first ApplicationContext is instantiated here
        // (it is also returned by the method).
        SpringApplication.run(DemoApplication.class, args);
    }

    /**
     * A new DispatcherServlet is instantiated and registered.
     */
    @Bean
    public ServletRegistrationBean mvc2() {

        // A new ApplicationContext is created, using a dedicated Configuration class.
        AnnotationConfigWebApplicationContext secondApplicationContext = new AnnotationConfigWebApplicationContext();
        secondApplicationContext.register(Mvc2Config.class);

        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        dispatcherServlet.setApplicationContext(secondApplicationContext);

        DispatcherServletRegistrationBean servletRegistrationBean = new DispatcherServletRegistrationBean(dispatcherServlet, "/second/*");
        servletRegistrationBean.setName("second");

        return servletRegistrationBean;
    }
}

In the same package we put also the controller that will be bounded to the default DispatcherServlet generated by Spring Boot:

@RestController
public class FirstController {

    @Autowired
    private MyApplicationScopeBean applicationScopeBean;

    @Autowired
    private MySingletonBean singletonBean;

    @GetMapping("/first/demo")
    public String output() {
        return "applicationScope=" + applicationScopeBean.getId() + ", singleton=" + singletonBean.getId();
    }
}

In the package com.example.demo.mvc2 we put the second configuration class:

@Configuration
@ComponentScan(basePackages = {"com.example.demo.mvc2", "com.example.demo.beans"})
@EnableWebMvc
public class Mvc2Config {
}

And the controller bounded to the second DispatcherServlet:

@RestController
public class SecondController {

    @Autowired
    private MyApplicationScopeBean applicationScopeBean;

    @Autowired
    private MySingletonBean singletonBean;

    @GetMapping("/demo")
    public String output() {
        return "applicationScope=" + applicationScopeBean.getId() + ", singleton=" + singletonBean.getId();
    }
}

If you run the code you can see that the id of the application scoped bean is the same in both the controllers, while the id of the singleton beans changes:

http://localhost:8080/first/demo

applicationScope=0.8685117272969953, singleton=0.23475401462261436

http://localhost:8080/second/demo

applicationScope=0.8685117272969953, singleton=0.8390865330171554

like image 70
xonya Avatar answered Sep 18 '22 12:09

xonya


https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-scopes-application

This is somewhat similar to a Spring singleton bean but differs in two important ways: It is a singleton per ServletContext, not per Spring 'ApplicationContext' (for which there may be several in any given web application), and it is actually exposed and therefore visible as a ServletContext attribute.

i.e. web application may have several Spring application contexts and therefore several instances of bean with singleton scope (one instance per spring app contexts) but only one bean defined with application scope.

like image 34
Evgeny Avatar answered Sep 21 '22 12:09

Evgeny