Spring in Action: A Spring Jump Start. Part 2
Spring in Action: A Spring Jump Start. Part 2
Written by Craig Walls and Ryan Breidenbach and reproduced from "Spring in Action" by permission of Manning Publications Co. ISBN 1932394354, copyright 2005. All rights reserved. See https://www.manning.com for more information.
1.4 Understanding inversion of control
Inversion of control is at the heart of the Spring framework. It may sound a bit intimidating, conjuring up notions of a complex programming technique or design pattern. But as it turns out, IoC is not nearly as complex as it sounds. In fact, by applying IoC in your projects, you'll find that your code will become significantly simpler, easier to understand, and easier to test. But what does "inversion of control" mean?
1.4.1 Injecting dependencies
In an article written in early 2004, Martin Fowler asked what aspect of control is being inverted. He concluded that it is the acquisition of dependent objects that is being inverted. Based on that revelation, he coined a better name for inversion of control: dependency injection.3
Any nontrivial application (pretty much anything more complex than Hello-World.java) is made up of two or more classes that collaborate with each other to perform some business logic. Traditionally, each object is responsible for obtaining its own references to the objects it collaborates with (its dependencies). As you'll see, this can lead to highly coupled and hard-to-test code.
Applying IoC, objects are given their dependencies at creation time by some external entity that coordinates each object in the system. That is, dependencies are injected into objects. So, IoC means an inversion of responsibility with regard to how an object obtains references to collaborating objects.
1.4.2 IoC in action
If you're like us, then you're probably anxious to see how this works in code. We aim to please, so without further delay
Suppose that your company's crack marketing team culled together the results of their expert market analysis and research and determined that what your customers need is a knight. That is, they need a Java class that represents a knight. After probing them for requirements, you learn that what they specifically want is for you to implement a class that represents an Arthurian knight of the Round Table that embarks on brave and noble quests to find the Holy Grail.
This is an odd request, but you've become accustomed to the strange notions and whims of the marketing team. So, without hesitation, you fire up your favorite IDE and bang out the class in listing 1.5.
3 Although we agree that "dependency injection" is a more accurate name than "inversion of control," we're likely to use both terms interchangeably in this book.
In listing 1.5 the knight is given a name as a parameter of its constructor. Its constructor
sets the knight's quest by instantiating a HolyGrailQuest
. The implementation
of HolyGrailQuest
is fairly trivial, as shown in listing 1.6.
Satisfied with your work, you proudly check the code into version control. You want to show it to the marketing team, but deep down something doesn't feel right. You almost dismiss it as the burrito you had for lunch when you realize the problem: you haven't written any unit tests.
Knightly testing
Unit testing is an important part of development. It not only ensures that each individual unit functions as expected, but it also serves to document each unit in the most accurate way possible. Seeking to rectify your failure to write unit tests, you put together the test case (listing 1.7) for your knight class.
After writing this test case, you set out to write a test case for HolyGrailQuest
. But
before you even get started, you realize that the KnightOfTheRoundTableTest
test
case indirectly tests HolyGrailQuest
. You also wonder if you are testing all contingencies.
What would happen if HolyGrailQuest's embark()
method returned
null? Or what if it were to throw a GrailNotFoundException
?
Created: March 27, 2003
Revised: March 17, 2005
URL: https://webreference.com/programing/spring/2