Bean Scopes in Java Springboot

Jayamal Jayamaha
8 min readNov 4, 2022

Non-related intro

In the last couple of days, I was attending some mock interviews with my peers in order to get practice for each one. Do you know what is the most interesting part of facing (mock or real) interviews? it is not about selecting for the next round, or it is not about thinking how many questions you did answer successfully but for me, it is about learning some new concepts that you that hasn’t been known earlier. This concept called “Bean Scope” is something that hasn’t been known earlier and was learned in one of a mock interview.

What is a bean

In the Spring context, a bean is an instance of a class that will be created and managed by the ApplicationContext of spring. In spring-boot when we annotate a class with @Component annotation, then that class will be eligible to be managed by ApplicationContext of spring. In the spring application context bean, it is working as a factory design pattern

As you can see in this image when the spring container starts it scans all the classes that are annotated by @Component annotation and then creates a bean of that classes. then afterward when you declare field level or constructor level dependency injections the bean factory will get the instance and inject it.

What is bean scope

Bean scope is something that we define with the @Scope annotation which tells the application context about how that particular bean should be created and presented throughout the application lifecycle. as an example default bean scope of spring is a singleton. singleton means a particular bean will be created at once when the application context starts and use that one bean throughout the application context.

Bean scopes in spring

Singleton (Default scope)

  • When you annotate a class with just the @Componentannotation but without @Scope annotation, this type of bean will be created.
  • In this scope, a particular bean will be created at once when the application starts, and use that one bean throughout the application.
  • This will be applicable same for the method-level bean creation as well. that means when we use @Bean annotation on methods.

Prototype

  • When you annotate a class with @Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)annotation after the @Component annotation, this type of bean will be created.
  • In this scope, a new instance of a particular class will be created and injected every time a bean of that class will be requested.
  • This will be applicable same for the method-level bean creation as well. that means when we use @Bean annotation on methods we need to define @Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS) after that
  • Will Discuss proxyMode at later part

Request

  • When you annotate a class with @Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)annotation after the @Component annotation, this type of bean will be created.
  • This scope is not available for normal standalone applications. this will be applicable to the java web applications context.
  • In this scope, a new instance of a particular class will be created and injected for each new HTTP request.
  • This will be applicable same for the method-level bean creation as well. that means when we use @Bean annotation on methods we need to define @Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) after that
  • Will Discuss proxyMode at later part

Session

  • When you annotate a class with @Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)annotation after the @Component annotation, this type of bean will be created.
  • This scope is not available for normal standalone applications. this will be applicable to the java web applications context.
  • In this scope, a new instance of a particular class will be created and injected for each new session for an HTTP request.
  • This will be applicable same for the method-level bean creation as well. that means when we use @Bean annotation on methods we need to define @Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) after that
  • Will Discuss proxyMode at later part

Application

  • When you annotate a class with @Scope(value=WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)annotation after the @Component annotation, this type of bean will be created.
  • In this scope, a new instance of a particular class will be created and injected for each new web application runtime.
  • This is more similar to singleton but in singleton, it is one instance per ApplicationContext but here it is one instance per ServletContext
  • Will Discuss proxyMode at later part

Custom Scope

  • Rather than using predefined scopes in spring-boot, we can create our own scope and use it.
  • There is an interface called Scope in org.springframework.beans.factory.config package. we need to implement our own scope class from that interface.

Bean Scope Bound Map

The above image shows the coverage scope of each bean in a spring application.

A prototype bean will be created every time when we ask for it, so it has the lowest coverage inside the application. On the other hand, a singleton bean will be created once per application context, so it has the maximum coverage inside the application. The rest of them will reside between both two of them.

There is an issue

Think of a situation, if you use a lower-level scope bean inside a higher-level scope bean. let's get an example and try to understand.

there is a singleton bean and inside that singleton bean there is a field and it is a type of prototype bean.

When the spring application starts, only one bean of SingletonBean will be created by the application context. That means only one prototype bean also be created and injected because all the dependencies will be injected when an object will be created. But that is not what we were trying to achieve using prototype beans.

Solutions

There is a solution to every problem in this universe. so there is a solution to the above problem as well.

Using the proxyMode inside @Scope annotation.

Strait forward approach is to use proxyMode = ScopedProxyMode.TARGET_CLASS inside @Scope annotation.

what happens when using this proxyMode is that the proxy object will be created for this PrototypeBean by spring ApplicationContext. when using some getter method of prototype bean, the application context will call to the getter method of that proxy class. then the proxy class will get the bean from the BeanFactory and call the getter method of the real bean.

When a bean is requested from BeanFactory, the BeanFactory will return the object based on the bean scope of that class. so it will return a new bean every time when prototype bean is requested.

Using @Lookup annotation

Here a new getter method for prototype bean will be created inside the singleton class, and then that method will be annotated with @Lookup annotation. the return type of that method will be null and that method will be overridden to return the actual bean in runtime by the application context.

Why this bean scope

As a mature person, you should always ask why do I need to do this in every situation in your life. By asking that question yourself, you will be able to find some hidden philosophies in this world. Following that we should also ask why the heck we need to care about this bean scope.

Actually knowing about this bean scope will help us in the following situations.

Singleton

  • If you have something to save, update and use that is web application specific within a web application context, then singleton is the best scope to use.
  • Using this scope will save memory because it will be created one bean for a web application context. So it is better to stick with this scope unless you have some specific requirements.
  • if the class is going to give some functional purpose rather than storing some specific variables for an object-to-object, this scope is the best to use. Better to use for services, repositories, and utility classes, because those types of classes have mostly functions rather than fields.

Prototype

  • If you need to work with some stateful components, then this is a good scope to use.
  • If you have a requirement to use threads or asynchronous flow with non-interdependent inputs, then this is a good bean scope to use inside threads.

Request

  • If you need a stateful component to store some HTTP request-specific details, then this is the scope you should go for.
  • If you need to store some request headers, or Auth tokens and use them later in the flow, then this is the scope you should go for.
  • If you need to store values for request-response inside each step or each class of the program, then request scope is the scope that you should use for the response bean of a particular object.

Session

  • If you need a stateful component to store some session-specific details, then this is the scope you should go for.
  • If you need to store some current session user information and use those details inside an entire session activity, then this is the ideal scope to use.

Application

  • If you need to store and access details across multiple web application contexts, you can’t use singleton but you can use this application scope bean.
  • One servlet context can have multiple web application contexts.

--

--