Complex Scenario of Spring Bean Scopes

In this article, we will discuss the complex scenario of Spring bean scopes. As we know the default bean scope of the bean is a singleton. Whenever we call getbean every time we will get the same bean instance from the application context. When application initialized JVM read all the configuration from the XML file or from the config class and loaded beans in the application context with a default bean scope singleton.

Spring Bean Scopes

To understand what happened in the background we need to enable the debug mode by adding below code in the application.properties file.

logging.level.org.springframework=debug

Show that we can identify what is happing in the background when we initialized the application.

Now in this article, we will discuss only prototype and singleton and its different way of use in the application.

Bean Scope
Singleton One instance per spring context
Prototype New bean whenever requested

Let’s create a java class to understand the above-mentioned scope.
RepoDaoLayer.java

@Component
public class RepoDaoLayer {

	 @Autowired
	 DatabaseConnection jdbcConnection;

	public DatabaseConnection getJdbcConnection() {
		return jdbcConnection;
	}

	public void setJdbcConnection(DatabaseConnection jdbcConnection) {
		this.jdbcConnection = jdbcConnection;
	}
}

As we can see in the above-mentioned code RepoDaoLayer has a dependency of DatabaseConnection bean. Whenever we initialized our application, spring will create an instance of DatabaseConnection along with an instance of RepoDaolayer.

Now let’s Create DatabaseConnection.java file

@Component
public class DatabaseConnection {

	
	 public DatabaseConnection() {
		 System.out.println("JDBC COONECITON");
	 }
}

Now Create DemoApplication.java main file to run the code.

@SpringBootApplication
public class DemoApplication {
static Logger LOG= LoggerFactory.getLogger(DemoApplication.class);
	public static void main(String[] args) {
			
ApplicationContextcxt=SpringApplication.run(DemoApplication.class, args);	
RepoDaoLayer dao= cxt.getBean(RepoDaoLayer.class);
	
LOG.info(dao.toString());
LOG.info(dao.getJdbcConnection().toString());
	
RepoDaoLayer da1= cxt.getBean(RepoDaoLayer.class);
LOG.info(da1.toString());
LOG.info(da1.getJdbcConnection().toString());
		
	}
}

As we can see we are getting two instances of RepoDaoLayer class using getBean. When we run the above code we will get below output:

spring bean scopes

Here we are getting the same instance of RepoDaolayer & DatabaseConnection every time because the default bean scope is the singleton.

Now What will happen when the parent class is prototype and child is a singleton?

Now I am making RepoDaoLayer.java class prototype. By using @scope(“prototype”) over RepoDaolayer.java class

@Component
@scope(“prototype”)
public class RepoDaoLayer {

...
}

Now run the main java file you will get below output:

output-2

As we can see in the screenshot we are getting the different instance of RepoDaolayer but same DatabaseConnection instance every time because of singleton nature of DatabaseConnection.

Now, what with happen if you make parent class as a singleton and child class as a prototype?

I am using @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) in DatabaseConnection.java class.

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DatabaseConnection {
...
}

Now run the main class. You will get the below output.

output-3
Now we can see we are getting same bean instances every time even we make DatabaseConnection class as a prototype? Why are we getting the same bean?

Because RepoDaoLayer class is singleton by nature and when we ask spring to give me bean of RepoDaolayer class it gives us a singleton bean without realizing that databaseConnection bean is the prototype.

If we really want to get different beans of DatabaseConnection whenever we request to Repodaolayer then we need to configure Proxy. The proxy will make sure that spring will give us new instances every time when we call RepoDaolayer bean. Below is the code to configure proxy bean of DatabaseConnecion.java class so that we can get new bean every time when we call Singleton bean.

@Component
@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE,proxyMode=ScopedProxyMode.TARGET_CLASS)
public class DatabaseConnection {
...
}

Here we use something called proxyMode=ScopedProxyMode.TARGET_CLASS. Which make sure that each time we get new bean when we call RepoDaoLayer. Now we can get different bean of DatabaseConnection every time when you get an instance of RepoDaolayer.

output-4

Here we can see we are getting same instance of RepoDaolayer but different instance of DatabaseConnection class because of proxy. Instead of giving DatabaseConnection object spring give us the proxy object of DatabaseConnection.

Previous
Next

10 Comments

  1. Dinesh Rajput July 21, 2018
  2. prashant singh July 22, 2018
  3. prashant singh July 22, 2018
  4. Naveen July 22, 2018
  5. Nasruddin July 22, 2018
  6. Swati Gupta July 22, 2018
  7. Aastha Bansal July 22, 2018
  8. Santosh July 23, 2018
  9. Santosh July 23, 2018
  10. Mohammad Fahim July 30, 2018