Dependency Injection - An Introductory Tutorial
Scopes and lifecycle
Spring supports the concepts of scopes. If you are familiar with JSP and Servlets, you may recall that they have request, session and application scopes. Objects put into request scope stay around for the duration of one request. Objects put into session scope stay around the entire user session (unless destroyed manually) while objects put into application scope stay around as long as the web application is running.
Spring scope support is very similar that of JSP and Servlets. Spring supports the following scopes: prototype, singleton, request, session and more. Plus you can configure you own scope handlers. Outside of a web application, Spring mainly supports two scopes out of the box: prototype and singleton. A singleton-scoped object is the default. It means that the object will stay around as long as the application context does (typically, very similar to application scope in a web application). A prototype scope means that every time that you ask for an object, Spring will create a new one. For example:
Two atms configured with different scopes
<bean id="atm" class="com.arcmind.springquickstart.AutomatedTellerMachineImpl" scope="singleton">
<constructor-arg index="0" ref="soapTransport" />
</bean>
<bean id="atmP" class="com.arcmind.springquickstart.AutomatedTellerMachineImpl" scope="prototype">
<constructor-arg index="0" ref="soapTransport" />
</bean>
If you looked up the atm twice, you would get the same object because it is in singleton scope; however, every time you looked up atmP, you would get a different object because it is in prototype scope. This is demonstrated by the following example:
Example demonstrating prototype vs. singleton
AutomatedTellerMachine atm1 = (AutomatedTellerMachine) appContext.getBean("atm");
AutomatedTellerMachine atm2 = (AutomatedTellerMachine) appContext.getBean("atm");
assert atm1 == atm2; //First assert
AutomatedTellerMachine atmP1 = (AutomatedTellerMachine) appContext.getBean("atmP");
AutomatedTellerMachine atmP2 = (AutomatedTellerMachine) appContext.getBean("atmP");
assert atmP1 != atmP2; //Second assert
Life cycle methods
Often times, you need an object to initialize itself after you have set all of the dependencies. Spring allows you to specify specify an init method as follows:
Specifying an init method with Spring (applicationContext.xml)
<bean id="atm" class="com.arcmind.springquickstart.AutomatedTellerMachineImpl" scope="singleton" init-method="init">
<constructor-arg index="0" ref="soapTransport" />
</bean>
<bean id="atmP" class="com.arcmind.springquickstart.AutomatedTellerMachineImpl" scope="prototype" init-method="init">
<constructor-arg index="0" ref="soapTransport" />
</bean>
Notice the use of the init-method attribute in the bean tag. The name of the method does not have to be init.
Here is the init method defined in Java. (There are also a few more methods for the transport to add to the flavor of the of the example and a shutdown method which the article will discuss in a moment).
Init Method and Shutdown method in Java
public class AutomatedTellerMachineImpl implements AutomatedTellerMachine{
public void init () {
System.out.println("INIT");
transport.connect();
}
public void shutdown () {
System.out.println("SHUTDOWN");
transport.close();
}
The atm bean's init method gets called right after your first load the application context (you can change this by setting the lazy-init attribute to "true"). The prototype atmP bean's init method gets called every time you look it up in the application context.
You can also specify a clean up method using the attribute destroy-method as follows:
Using destroy-method attribute
<bean id="atm" class="com.arcmind.springquickstart.AutomatedTellerMachineImpl" scope="singleton"
init-method="init" destroy-method="shutdown">
<constructor-arg index="0" ref="soapTransport" />
</bean>
<bean id="atmP" class="com.arcmind.springquickstart.AutomatedTellerMachineImpl" scope="prototype"
init-method="init" destroy-method="shutdown">
<constructor-arg index="0" ref="soapTransport" />
</bean>
The destroy method would never get called by Spring on atmP because it does not manage the life cycle of prototype beans after creation. The destroy method on atm would only get called if someone gracefully closed the application context which Spring does for some application contexts (this is beyond the scope of this introductory tutorial). Figure 10 illustrates using lifecycle methods.

Conclusion
DI can help make your code architecturally pure. It aids in using a design-by-interface approach as well as test-driven development by providing a consistent way to inject dependencies. You don't need Spring to use DI. You could use DI with plain old Java. However, Spring provides a very nice, powerful DI container.
There are other DI containers and frameworks out there such as Plexus, Pico container, JBoss microcontainer, and, more recently, Guice. And, other frameworks allow DI like JSF, Seam and more. But, Spring is the de facto industry standard way to do DI.
What we did not cover is also interesting. We did not cover autowiring using by type or by name or constructor autowiring as these are features that developers just don't use in a production environments. A future tutorial titled, "DI details", will cover this as well as many other topics related to Spring DI like bean definitions, using lists, maps and sets, FactoryBeans, ApplicationContextAware, and, yes, autowiring.
The next item in this tutorial series will be AOP. Followed by Spring DAO and JPA support.
Rick Hightower serves as Chief Technology Officer for ArcMind Inc., a consulting and training firm specializing in Spring, JPA/Hibernate, and JSF. Rick enjoys writing and programming.
- Login or register to post comments
- 33328 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)










Comments
dzoneCody replied on Tue, 2008/11/11 - 8:40am
Very nice article,
One of my biggest obstacles has been grasping DI conceptionally. I think you did a good job in showing the "tutorial" perspective of DI. Can't wait to see more...
Rick Hightower replied on Thu, 2008/11/13 - 12:09pm
Jakob Jenkov replied on Tue, 2008/11/11 - 2:55pm
Hi Rick,
I just browsed the article quickly. Seems you have spent a long time putting this piece together! Kudos to you!
If I may comment a bit on the title, I think it is perhaps slightly mis-leading. This article, though definately useful, is more of a "Dependency Injection with Spring"-tutorial. Some of the concepts are unique to Spring, and the configuration examples definately are too. But readers new to dependency injection could be lead to believe, that dependency injection is only something you can do with Spring. But there are Pico, Guice and Butterfly Container too, among others.
You do mention Spring early on page 1, so I guess the "mislead" reader is quickly corrected. Anyways, with frameworks growing as huge as Spring is, it is nice with "getting started / introductory" articles like this one.
I too wrote a tutorial on dependency injection, but my tutorial tries to explain the concept a bit more detached from any specific DI container (yet it shows examples using Butterfly DI Container). In the end of this tutorial I also explain when and when NOT to use dependency injection (according to my opinion / experience).
Rick Hightower replied on Tue, 2008/11/11 - 3:05pm
in response to: jj83777
digitalcorndawg replied on Tue, 2008/11/11 - 3:05pm
hovo73 replied on Tue, 2008/11/11 - 3:06pm
cmathias replied on Tue, 2008/11/11 - 3:09pm
Nice article Rick. I love the DI concept, but I struggled with it at first, as I imagine most developers do who have been authoring more traditional workhorse code. I find it amazing how using things like Spring let me get down to business...most of my code these days actually does only what it needs to do rather than taking twenty lines to set up the three important ones.
I think it's great that heavyweights like yourself that really 'get' this stuff take the time to turn back, and teach the rest who are lagging.
I would disagree with Jakob's observation as I feel you did mention alternatives more than once. (though yes, your samples are Spring). Spring has become a monster, but from my experiences so far, is still the sharpest knive in the drawer.
Keep it up Rick - the one I'm personally waiting for is the AspectJ introduction (specifically tapping cut points in compiled libraries). Can you just DI that into my head please?
tac replied on Tue, 2008/11/11 - 3:21pm
excellent concrete example of using dependency injection. I am a long-time Spring user but there were several useful pieces of information on some of the newer features. I will definitely add the 'p:' tags to my toolkit. Thanks,
-tom
Paul Hixson replied on Tue, 2008/11/11 - 3:24pm
Jakob Jenkov replied on Tue, 2008/11/11 - 3:59pm
Walter Bogaardt replied on Tue, 2008/11/11 - 4:38pm
Great explanation. I was wondering what happens to the role of the applicationContext with all the annotations. It was one of those todo things to look at when I had some cycles, and you cleared it up in a few lines.
I'd like to see something on the spring annotations features like @Bean and javaconfig, and spring or DI in the web world of servlets, jsf, jsp. Keep up the good articles.
Steven replied on Wed, 2008/11/12 - 6:41am
great read, but it feels like it missed a key part: actually integrating spring into an app.
i.e. starting it up, adding the context/listener to web.xml or something similar like even using the bean factory.
Stuart Halloway replied on Wed, 2008/11/12 - 9:15am
Hi Rick,
Responding per your request for comments. I found the tutotial easy-to-follow, but I don't want to follow where it goes. :-) I think DI is overrated, and both XML and Annotations are bad ways to do it. If a team is committed to DI, I would recommend a Groovy, JRuby, or Clojure based DSL.
Cheers,
Stuart
johnfryar replied on Wed, 2008/11/12 - 9:53am
You have particular skill with examples. The examples you provide here, as with your JSF tutorial on developerworks, are USEFUL and clearly illustrate some key concepts. The images you use to highlight how the xml is related to the java code and how the annotated classes related one-to-another are top-notch. You could probably expand that approach into a book and it would be very helpful to both newbies and experience Spring developers.
I agree with Jakob that the title is misleading. This really isn't about DI so much as it is about DI using Spring. That being said, it's a fantastic article for anyone looking for an introduction to DI using Spring.
I look forward to the follow-up articles.
Solomon replied on Wed, 2008/11/12 - 2:06pm
This is a follow up to your linkedIn question:
I'd like to revise this question a bit to: "When should you annotate a class with Injection configuration, and when should you externalize the Injection configuration?"
IMHO, the more generic question is key on how you should think about DI. 80-90% of the time you can annotate a class with DI info. The types of annotations you're adding are "I need an instance of X class injected here" (for example Spring's @Autowired and @Required, JEE's @Resource and Guice's @Inject), "I am available for use" (Spring's @Component/@Service/@Controller/@Repository, JEE's @Stateless/..., and Guice's @ImplementedBy/@Singleton/...), and "I need/am a specific instance of X class/interface" (Spring's @Qualifier, and Guice's @BindingAnnotation).
There are quite a few reasons for the other 10-20% of cases that don't make sense, and for those, DI configuration needs to be put somewhere else, for example in Spring XML, Spring JavaConfig or Guice Modules/Producers. Some of the reasons are:
1) The class is defined in a location that you don't have control over, such as a vendor jar.
2) The class encapsulates an environmental configuration, such as setting up a DataSource or Hibernate configuration
3) You need more than one instance of the same exact class
Some cases have a 100% need to be externalized (for example, database and hibernate). However, there are plenty of cases that are pretty tricky to either categorize or implement.
One quick example of a borderline common case is a Spring @Controller. I often configure MVC Controllers with a JSP file or Tile that I'd like to use. You can do that by injecting a String value (with a Qualifier "mySuccssView") into the controller; however, Spring doesn't let you use the @Autowired annotation, you have to use JEE's @Resource annotation, or use XML. By the way, the definition of the mySuccssView in Spring XML took 3 lines of code!!! Anyway, I was using WebSphere 6.1, and had to opt out of the @Resource because of classpath issues, so I had to use the XML config. The problem with the XML config is that @Controller servers two purposes: 1) defining a Role in the system, 2) defining the class as "I am available for use in a DI use" as part of classpath scanning and default autowiring. I wanted to set the value the value in XML, therefore the classpath scanning part of #2 was out of the question. To do that, I had to customize the component scanning with a Spring "context:exclude-filter."
The point of that example is that there are still plenty of gotchas that need to be ironed out. Guice is slightly ahead of Spring on those kinds of annotation gotchas. One of the most seemingly obvious abilities that Guice has is the import of key/value pairs into the module (a.k.a. "application context") as seen in this thread in the Guice News Group.
There's a lot more to this topic, but I hope that I've she some more light on this esoteric subject.
jordanz replied on Wed, 2008/11/12 - 5:42pm
Solomon replied on Wed, 2008/11/12 - 7:22pm
in response to: jordanz
Here we go again. This argument is so 2004. I assume that you've read good old Martin Fowler's article on the subject.
DI moved away from Singletons and JNDI lookups. IHMO, DI's been a great boon for the quality and clarity of my code base. XML and annotation aren't code, they are indeed declarative configuration and possibly meta-programming.
You are correct. The term "Configuration" does apply. Usually I think about "Configuration" in the context of environment related setup. DI does make environmental configuration a lot simpler. However, it also adds in the ability to separate out how a particular class does its work and participates with other classes from how that class is exposed and how that class finds instances of other classes.
Yeah, at the end of the day DI is "Configuration", but its configuration that inherently replaces the code you as a developer have to write for the types of things covered by Creational and Structural Design Patterns.
jordanz replied on Wed, 2008/11/12 - 7:46pm
in response to: sduskis
I've read most articles on the subject. Yes, the counter-arguments have been going on for a long time. That doesn't mean that the subject is settled.
Solomon replied on Wed, 2008/11/12 - 8:30pm
in response to: jordanz
I've read most articles on the subject. Yes, the counter-arguments have been going on for a long time. That doesn't mean that the subject is settled.
[/quote]You're right. The subject of DI is not settled yet. But dismissing it as "just configuration" and something that "was done in software practice for years" doesn't seem to do it justice. We mortals do need simple phrases for complex concepts that DI solves like dependency management, environmental configuration and separation of concerns. There are other methodologies of solving those same needs. There are also different imlementations of DI that have plenty of merit.
With that said, comments like "Why not call this what we've always called this: Configuration. Everyone knows what that is." don't seem to lead the direction of the communal conversation towards "settling" the subject.
jordanz replied on Wed, 2008/11/12 - 9:43pm
in response to: sduskis
Actually, I somewhat agree with you. Depenency Injection, however, is an unnecessarily obscure term. When I first heard I had no idea whatsoever what it meant. Automated Configuration is more descriptive. The name of the concept should give a clue as to the content of the concept. Having such an abstract name has allowed DI to mean whatever anyone wants it to mean.
Solomon replied on Thu, 2008/11/13 - 10:06am
in response to: jordanz
Actually, I somewhat agree with you. Depenency Injection, however, is an unnecessarily obscure term. When I first heard I had no idea whatsoever what it meant. Automated Configuration is more descriptive. The name of the concept should give a clue as to the content of the concept. Having such an abstract name has allowed DI to mean whatever anyone wants it to mean.
[/quote]
DiP defines how objects interact with each other and that an object that encapsulates some behavior (DAO, service, UI and etc) should never (or rarely) look up or instantiate another behavior-driven dependency. Those dependencies can be either it another object or some configuration setting. DiP says that in order to get those dependencies, some external assembly system (either a framework, or hand-coding) should assemble the application and "inject" specific dependencies as needed.
In other words, you can adhere to the DI Principle without any configuration. It's the Dependency Injection Frameworks that use configuration to create a solution that adheres to DiP.
ravihasija replied on Thu, 2008/11/13 - 11:23am
This is a great article. Led by example, and not dry by just providing theory. Simple, yet beautiful. Kudos to you for creating this. I have a firm grasp of what Spring and DI (in general) is.
I would love to have such articles on other topics like Hibernate, EhCache, Struts, EJB, JSP, etc to name a few. Probably they are already out there on this website. If not then, something to consider ;-)
Thank you so much!
Sincerely,
Ravi
Rick Hightower replied on Thu, 2008/11/13 - 12:10pm
Rick Hightower replied on Thu, 2008/11/13 - 2:35pm
in response to: ravihasija
Thanks Ravi. I really appreciate the positive feedback. It really helps. Thanks.
Bruno Sofiato replied on Fri, 2008/11/14 - 6:33pm
Cool article.
I personally don't like the current annotation usage model spread on the majority of the frameworks, guys configuration isn't meta-data. Annotations IMHO should be used to express semantical information within the code itself. The @Required annotations got it right. The ATMTransport is required by the AutomatedTellerMachineImpl class, thats an implementation detail of that class, the @Required is expressing a semantical info.
The @Autowired and the @Qualifier on the otherside are expressing config details. They are linking an property value to an named instance on the bean container. Should a class know which named instances will be injected on it's instances ? I think it should not.
Rick Hightower replied on Fri, 2008/11/14 - 11:08pm
in response to: Bruno Sofiato
Bruno Sofiato replied on Sat, 2008/11/15 - 10:42am
in response to: rhightower
Yes, some objects were made to collaborate with others, but maybe the property declaration would provide this kind of info.
I agree that annotations are a popular aproach these days, maybe it's a consequence of this grudge against XML based configuration that is wildspread among the Java developer's ranks.
Just my 2 cents.
William Willems replied on Mon, 2008/11/17 - 5:54am
nitin pai replied on Mon, 2008/11/17 - 10:13pm
Rick - Thanks a ton. This timing of this article has been perfect to match with my intentions. I wanted to make my team understand the concepts of Spring such as DI, IOC, AOP etc. And you have just eased out my work since I do not have to compile the articles myself. This article is simply to the point.
Eagerly waiting for your further articles on Spring features. And if you require any help just let me know. I am on the same track too :)
george.jiang replied on Tue, 2008/11/18 - 9:43pm
The best introduction to Spring 2.5 DI. Better than those published Spring books.
Rick, when will the intoduction article to Spring AOP be out? Thanks.