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
| 191579 views |
  • submit to reddit

This article discusses dependency injection in a tutorial format. It covers some of the newer features of Spring DI such as annotations, improved XML configuration and more.

Dependency Injection

Dependency Injection (DI) refers to the process of supplying an external dependency to a software component. DI can help make your code architecturally pure. It aids in design by interface as well as test-driven development by providing a consistent way to inject dependencies. For example, a data access object (DAO) may depend on a database connection. Instead of looking up the database connection with JNDI, you could inject it.

One way to think about a DI container like Spring is to think of JNDI turned inside out. Instead of an object looking up other objects that it needs to get its job done (dependencies), a DI container injects those dependent objects. This is the so-called Hollywood Principle, “Don't call us” (lookup objects), “we’ll call you” (inject objects).

If you have worked with CRC cards you can think of a dependency as a collaborator, i.e., an object that another object needs to perform its role.
Let's say that you have an automated teller machine (ATM) and it needs the ability to talk to a bank. It uses what it calls a transport object to do this. In this example, a transport object handles the low-level communication to the bank.

This example could be represented by either of the  two interfaces as follows:

AutomatedTellerMachine interface

package com.arcmind.springquickstart;

import java.math.BigDecimal;

public interface AutomatedTellerMachine {
        void deposit(BigDecimal bd);
        void withdraw(BigDecimal bd);
}

 

ATMTransport interface

package com.arcmind.springquickstart;

public interface ATMTransport {
        void communicateWithBank(byte [] datapacket);
}

Now the AutomatedTellerMachine needs a transport to perform its intent, namely withdraw money and deposit money. To carry out these tasks, the AutomatedTellerMachine may depend on many objects and collaborates with its dependencies to complete the work.

An implementation of the AutomatedTellerMachine may look like this:

AutomatedTellerMachine implementation:

package com.arcmind.springquickstart;

import java.math.BigDecimal;

public class AutomatedTellerMachineImpl implements AutomatedTellerMachine{
        
        private ATMTransport transport;
        
        public void deposit(BigDecimal bd) {
          ...
                transport.communicateWithBank(...);
        }

        public void withdraw(BigDecimal bd) {
          ...
                transport.communicateWithBank(...);
        }

        public void setTransport(ATMTransport transport) {
                this.transport = transport;
        }
        
}
 

The AutomatedTellerMachineImpl does not know or care how the transport withdraws and deposits money from the bank. This level of indirection allows us to replace the transport with different implementations such as in the following example:

Three example transports: SoapAtmTransport, StandardAtmTransport and SimulationAtmTransport

package com.arcmind.springquickstart;

public class SoapAtmTransport implements ATMTransport {

        public void communicateWithBank(byte[] datapacket) {
           ...
        }

}
package com.arcmind.springquickstart;

public class StandardAtmTransport implements ATMTransport {

        public void communicateWithBank(byte[] datapacket) {
          ...
        }

}

 

package com.arcmind.springquickstart;

public class SimulationAtmTransport implements ATMTransport {

        public void communicateWithBank(byte[] datapacket) {
                ...
        }

}

 

Notice the possible implementations of the ATMTransport interface. The AutomatedTellerMachineImpl does not know or care which transport it uses. Also, for testing and developing, instead of talking to a real bank, notice that you can use the SimulationAtmTransport.



About the author

Rick Hightower is CTO of Mammatus and is an expert on Java and Cloud Computing. Rick is invovled in Java CDI advocacy and Java EE. CDI Implementations - Resin Candi - Seam Weld - Apache OpenWebBeans

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.