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

Murphree Mukada replied on Thu, 2008/11/27 - 7:48am

Brilliant! Concise and clear. Thanks a million Rick.

Rick Hightower replied on Sun, 2008/11/30 - 6:33pm in response to: George Jiang

The Spring AOP article has been written and is waiting to be copy edited.

Viraf Karai replied on Sat, 2009/02/21 - 3:14pm

Well written, but it might still be a tad difficult for newcomers to Spring to grasp fully.

I'm not in the anti-XML camp, so I don't feel very comfortable with this new trend towards using annotations willy-nilly. In fact I feel that it diminishes the ability to view the big picture. I do like the new 'context' and 'p' namespaces. Some of the annotations like @Required and @Transactional have been well-thought out by the SpringSource folks and I commend them for that.

Just one final note and it's not meant to be a sales pitch - IntelliJ IDEA 8.x has brilliant Spring support and provides really good code completion as well as linking Java interfaces with Spring bean definitions. I've been using it for about 8 months now and am continually amazed at it's capabilities.

Looking forward to your future articles - especially AOP - a great passion of mine.

Rick Reumann replied on Tue, 2009/09/01 - 2:54pm

I'm really curious though, how often do people have that many different implementations at application startup time? I've been using Spring and Guice for a while now and often when I've completed my app I look back and wonder "ok, what did I really gain here having my concrete implemenations defined in an xml or single Java file?"

 I don't care much about using Mock objects in Testing either, but if I did, I could definitely see the advantage of DI there. 

 Of course I like containers doing some DI for me, like the EJB3 DI stuff etc, but in your typical CRUD app I simply find that I've added one more layer of abstraction that isn't needed. In the early days I was also always a purist and coded everything to an Interface - but in real life, how often, for example, are you swapping out Service class or DAO implemnations? 

 I feel like a heretic and wondering if I'm alone :)

 

Pradeep Kumar replied on Wed, 2012/09/19 - 12:59pm

Very nice, no words thanks much..!!

But please add spring MVC 3.0 also.

Krishna Pokala replied on Tue, 2012/10/02 - 9:08am

Superb intro to DI. Thanks Rick

Comment viewing options

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