Rick has posted 25 posts at DZone. You can read more from them at their website. View Full User Profile

Spring Dependency Injection - An Introductory Tutorial

11.11.2008
| 193443 views |
  • submit to reddit
 

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.

Published at DZone with permission of its author, Rick Hightower.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Cody A_ 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

Quick question... When should you use Spring Annotations for DI and when should you use Spring XML for DI?

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: Jakob Jenkov

Thanks Jakob, I will read that. There were a few spots in the tutorial where I explain that DI is not tied to Spring and I do mention many of the frameworks that you mentioned and a few that you did not. :)

Geoffrey Chandler replied on Tue, 2008/11/11 - 3:05pm

This is a very good article.  Nicely done, Rick.  There is a lot of noise out there about different ways to do DI, even in Spring (xml vs java, etc) and I've found that this can be confusing to people new to DI in general.  I've been advocating DI in my department, and have suggested lots of reading material over the last couple months to my coworkers.  A lot of it has been received with a fair amount of skepticism and confusion, largely due to the lack of a clear outline of DI as a concept.  I will be passing on this article to all of them.  Thank you very much for putting time into creating this!

Hovanes Gambaryan replied on Tue, 2008/11/11 - 3:06pm

Thank you Mr. Hightower. Your article is very helpful.

chris mathias 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?

 

 

Tom Cellucci 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

Even though I work with Srping on a daily basis, I always get something fresh from Rick's articles.  This time it was the property-placeholder concept.  I hate programming in XML and especially hate tweaking XML for various deployment environments.  Thanks much Rick!!

Jakob Jenkov replied on Tue, 2008/11/11 - 3:59pm

:-) ... my tutorial isn't perfect either. Just a slightly different focus. I don't mention many frameworks at all, except by name. People like this article. It's good work! I am currenctly on a Spring project, so I might read it a bit more careful the following days, to pick up tricks about new features. Thanks!

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 Baker 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 

John Fryar 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 Duskis replied on Wed, 2008/11/12 - 2:06pm

This is a follow up to your linkedIn question:

When should you use Spring Annotations for DI and when should you use Spring XML for DI?

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.

Jordan Zimmerman replied on Wed, 2008/11/12 - 5:42pm

Thank you for this. Your article reinforces for me why I so dislike the Spring trend in architecture. The term "Dependency Injection" is unnecessarily obtuse. Why was a new term of art needed for something that has been done in software practice for years. The "DI" has merely moved code from Java to a different language (XML or annotations). Why not call this what we've always called this: Configuration. Everyone knows what that is.

Solomon Duskis replied on Wed, 2008/11/12 - 7:22pm in response to: Jordan Zimmerman

 The term "Dependency Injection" is unnecessarily obtuse. Why was a new term of art needed for something that has been done in software practice for years.

Here we go again.  This argument is so 2004.  I assume that you've read good old Martin Fowler's article on the subject.

The "DI" has merely moved code from Java to a different language (XML or annotations).

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.

Why not call this what we've always called this: Configuration. Everyone knows what that is.

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.

Jordan Zimmerman replied on Wed, 2008/11/12 - 7:46pm in response to: Solomon Duskis

Here we go again.  This argument is so 2004.  I assume that you've read good old Martin Fowler's article on the subject.

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 Duskis replied on Wed, 2008/11/12 - 8:30pm in response to: Jordan Zimmerman

[quote=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.

Jordan Zimmerman replied on Wed, 2008/11/12 - 9:43pm in response to: Solomon Duskis

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.

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 Duskis replied on Thu, 2008/11/13 - 10:06am in response to: Jordan Zimmerman

[quote=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.

Ravi Hasija 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

When should you use Spring Annotations for DI and when should you use Spring XML for DI? I have some ideas/opinions on this, but was curious what you guys felt.

Rick Hightower replied on Thu, 2008/11/13 - 2:35pm in response to: Ravi Hasija

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

I think you make a good point, however, there are some objects that were made to collaborate with others. Having a default injection makes the object easier to work with. And, you can always override the default injection with XML if needed. Any way... just my two cents. I am not 100% convinced on this approach but it seems to be a popular one and I for one am warming up to it.

Bruno Sofiato replied on Sat, 2008/11/15 - 10:42am in response to: Rick Hightower

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

Very nice and clear article. Was not aware of the existence of the @Qualifier tag. Thanks.

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.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.