Injecting Prototype Beans in Singletons

Introduction

This is a series and it would make a lot of sense if read in a sequence. You can find all the posts under the heading “Spring Beginners to Professionals“. In the previous posts,we talked about scopes of Spring beans. Now as there are many different scopes, the basic problem which arises is injecting prototype beans in singletons. We can also define this problem in a more general way, say collaboration between beans of different scopes.

Injecting Prototype Beans in Singletons

By now we have learnt that the dependency injection happens when the container starts. All the singletons are initialized, their dependencies satisfied and they are cached in the singleton cache. Now, imagine having a prototype bean dependency injected in a singleton.

Why is this a big fuss?

When the singleton is created, a new instance of the prototype bean is created and injected in the singleton bean. This causes a problem when someone requests for the prototype bean through the singleton.

  • It can return the only instance of the prototype bean it knows.
  • It won’t ever inject a new prototype bean into it and return it,

This happened because the injection is done by the container and the container already injected the prototype bean  while starting. This defies the purpose of defining the prototype bean. That is why it is a topic of discussion.

Do we really have such a scenario?

To answer this, let me create a hypothetical use cases. In many large scale web applications it is required to identify the customers uniquely, there are some scenarios where each request from the same customer has to be tagged uniquely and archived. In such a scenario, it becomes important to have a id generation strategy, possibly UUID or GUID.

So I define a prototype scoped GUID bean as below.

And then I define a GuidSupplier bean.

Now let us configure the Guid bean as prototype and GuidSupplier as singleton and inject the Guid in the GuidSupplier using a setter injection.

Let us also write a Runner program to bootstrap all this and run.

In the above code, I am fetching the guid three times, and no matter how many times I fetch it, it will always return the same value for the reasons explained above. This is not expected.

How do we fix this ?

There are ways of fixing this, one of them is to let go some dependency injection. Instead of injecting the prototype bean into singleton bean, the bean is fetched from the application context each time it is needed.

So let us write a new GuidSupplier as below:

Now let us configure the Guid bean as prototype and GuidSupplier as singleton and inject the Guid in the GuidSupplier using a setter injection.

And now you can run it using the below runner:

The above method works, but it is no fun. We are unnecessarily coupling our application logic with Spring APIs. It becomes dependent on the Spring API classes and hence, is not a good design.

Also, we didn’t learn so much of Spring to let go dependency injection, so specially to handle this scenario Spring offers a different technique called lookup method injection.

Understanding Lookup Method Injection

This technique enforces spring to inject dependency using a method of the singleton bean. Spring creates a subclass of the singleton bean and implements/override the lookup method to return a new instance of the prototype bean when requested.

Here is the abstract class which is treated as the singleton bean

Here, the createGuid is the lookup method which must be overriden by Spring container. Below is the bean definition in the XML

And this is how the runner will invoke it

This of course is done using the CGLIB library as it requires byte code manipulation. Couple of things which must be taken into account while defining the singleton bean in this case is:

  • It must not be declared final as it has to be sub classed.
  • The look up method must not be final or private as it has to be overridden

So as you see, if Spring completely controls the bean instantiation then it would definitely be able to sub class the singleton bean and perform look up method injection. But still, things can go wrong, when the instantiation is not controlled by Spring completely.

For e.g.: In the Constructor Injection post we learnt that a bean definition can optionally accept a factory method which defines the way a bean can be created. This is a severe limitation in implementing look up method injection. As in the factory method case the bean instantiation is not completely controlled by the Spring IoC container.

Summary

This post helps us understand the issues related to bean injections where beans are from different scopes. Lookup method injection is an important topic, it is asked in many interviews. There are quite a few bean scopes and we must discuss them in some details in the next post.

Please let me know in comments if things were not clear, I would be happy to add that explanation. Stay connected.

 

  • deepti mittal

    Amazing post.