If we elevate ourselves enough to sit on a figurative perch in the programming world and look down at the applications that are being developed, we realize that Inversion of Control (IoC) containers have most definitely come here to stay. You see more people than ever before proclaiming expertise in programming "Java with Springs" - alluding no doubt to the Spring lightweight container that has now become the de-facto choice to develop most modern J2EE applications. Now it is easier than ever to create components as "Stateless Singletons" and injecting other stateless singletons into them. The whole dependency tree gets materialized during start up. Given this background, I was somewhat surprised and fascinated by two independent problems that were recently brought to my attention.
The problems involved different IoC containers - one of them being Spring and the other being ATG Nucleus. Both stated the same thing namely that the application is taking too long to look up components from the IoC containers. Ex: In Spring, the SpringBeanFactory.getBean(String name) call was taking too long. Now, if you were an application doctor who got commissioned to solve this case, your natural temptation is to prescribe the following:
Thou shalt not useth an IoC container to look up components. Use it instead to inject one component into the other during start up.
But before you scribble these words of profound wisdom with an illegible hand, as doctors are wont to do, you would do well to take a small pause and consider the situation more holistically. Why is a component forced to "look up" other components from an IoC container? In other words, what are the situations that would warrant one component being forced to look up another component? Components need to look up other components if they cannot benefit from injection. The only reason that such a thing happens is if the two components are in different scopes. In the case of a Spring application, one component might be a singleton whilst its dependency maybe a "prototype". Hence the singleton component has to "look up" the prototype component. It can do so either by either using BeanFactoryAware interfaces or method injection. (Please see here for a detailed description for both these artifices in Spring)
But the point I am making is to figure out "why" we need to have components in different scopes. In general, I would look askance at any attempt to use a component as a non singleton. My reasoning is as follows: If you use a component as a non singleton, then it implies that you are storing some kind of state in that component. This state may be instance specific , request specific, session specific etc. This is mostly not required. But the following use cases may warrant them:
- We may be using a framework that requires stateful components. Ex: All actions in Struts 2 are considered stateful since the framework injects request specific parameters (stuff that got submitted by the user) into the component.
- We maybe using value objects to store components. Consider a situation where a value object contains a method that invokes a strategy to act on it. Ex: We may have an XmlRenderer component that renders other objects to XML. A value object may have a render() method that invokes this renderer to render itself to XML.
In the above situations, the class in question acts as both a carrier of state as well as something that accomplishes some work. This kind of mixup of responsibilities leads to a situation where a more ephemeral object (ex: the value object or the struts 2 action) needs to look up a singleton component that is naturally contained in an IoC container. A ton of post processors (using the Spring parlance) come into play in this lookup which can lead to a substantial slowness of this call.
Note that in the above discussion, we did not discuss another candidate use case that requires a component lookup from an IoC container. This happens in writing frameworks. Let us say that we write a framework that requires a component to be created by the client of the framework. (such as for instance an MVC framework such as Struts) This component might require us to look up actions that are best created by an IoC container. In this case, we need to look up the component when the request to be serviced by the component arrives. (in Struts case, the request hits a URL that is mapped to a struts action). At that point in time, we can either look up the component from the IoC container which is unavoidable.
These kind of problems are best avoided by the judicious separation of data containers from the strategies in an application. I am well aware that this may tilt the design excessively towards an anemic domain model which is frowned upon by the purists of object design. My point is that the term Anemic Data Model has itself been coined with prejudice. You can always have strategies that leverage inheritance rather than becoming transaction scripts.
Just my point of view!