By Craig Walls and Ryan Breidenbach
Giving and taking

The question you should be asking at this point is whether or not a knight should be responsible for obtaining a quest. Or, should a knight be given a quest to embark upon?

Consider the following change to KnightOfTheRoundTable:

public class KnightOfTheRoundTable implements Knight {
   private Quest quest;
   ...

   public KnightOfTheRoundTable(String name) {
      ...
   }

   public HolyGrail embarkOnQuest() throws QuestException {
      ...
      return quest.embark();
   }

   public void setQuest(Quest quest) {
      this.quest = quest;
   }
}

Notice the difference? Compare figure 1.3 with figure 1.2 to see the difference in how a knight obtains its quest. Now the knight is given a quest instead of retrieving one itself. KnightOfTheRoundTable is no longer responsible for retrieving its own quests. And because it only knows about a quest through the Quest interface, you could give a knight any implementation of Quest you want. In a production system, maybe you would give it a HolyGrailQuest, but in a test case you would give it a mock implementation of Quest.

In a nutshell, that is what inversion of control is all about: the responsibility of coordinating collaboration between dependent objects is transferred away from the objects themselves. And that's where lightweight container frameworks, such as Spring, come into play.

Assigning a quest to a knight

Now that you've written your KnightOfTheRoundTable class to be given any arbitrary Quest object, how can you specify which Quest it should be given?

A Spring Jump Start.Part.IV_第1张图片

Figure 1.3 A knight is given a quest through its setQuest() method.

The act of creating associations between application components is referred to as wiring. In Spring, there are many ways to wire components together, but the most common approach is via XML. Listing 1.8 shows a simple Spring configuration file, knight.xml, that gives a quest (specifically, a HolyGrailQuest) to a KnightOfTheRoundTable.

Listing 1.8 Wiring a quest to a knight in knight.xml


A Spring Jump Start.Part.IV_第2张图片
Click here for a larger image.

This is just a simple approach to wiring beans. Don't worry too much about the details of it right now. In chapter 2 we'll explain more about what is going on here, as well as show you even more ways you can wire your beans in Spring.

Now that we've declared the relationship between a knight and a quest, we need to load up the XML file and kick off the application.

Seeing it work

In a Spring application, a BeanFactory loads the bean definitions and wires the beans together. Because the beans in the knight example are declared in an XML file, an XmlBeanFactory is the appropriate factory for this example. The main() method in listing 1.9 uses an XmlBeanFactory to load knight.xml and to get a reference to the "knight" object.

Listing 1.9 Running the knight example


A Spring Jump Start.Part.IV_第3张图片
Click here for a larger image.

Once the application has a reference to the KnightOfTheRoundTable object, it simply calls the embarkOnQuest() method to kick off the knight's adventure. Notice that this class knows nothing about the quest the knight will take. Again, the only thing that knows which type of quest will be given to the knight is the knight.xml file.

It's been a lot of fun sending knights on quests using inversion of control, but now let's see how you can use IoC in your real-world enterprise applications.4

1.4.3 IoC in enterprise applications

Suppose that you've been tasked with writing an online shopping application. Included in the application is an OrderServiceBean, implemented as a stateless session bean. Now you want to have a class that creates an Order object from user input (likely an HTML form) and call the createOrder() method on your OrderServiceBean, as shown in listing 1.10.

Listing 1.10 Creating an order using EJB


A Spring Jump Start.Part.IV_第4张图片
Click here for a larger image.

Notice that it took five lines of code just to get your OrderService object. Now imagine having to do this everywhere you need an OrderService object. Now imagine you have ten other EJBs in your application. That is a lot of code! But duplicating this code everywhere would be ridiculous, so a ServiceLocator is typically used instead. A ServiceLocator acts as a central point for obtaining and caching EJBHome references:

private OrderService getOrderService() {
   OrderServiceHome home =
      ServiceLocator.locate(OrderServiceHome);
   OrderService orderService = home.create();
}

While this removes the need to duplicate the lookup code everywhere in the application, one problem still remains: we always have to explicitly look up our services in our code.

Now let's see how this would be implemented in Spring:

private OrderService orderService;

public void doRequest(HttpServletRequest request) {
   Order order = createOrder(request);
   orderService.createOrder(order);
}

public void setOrderService(OrderService orderService) {
   this.orderService = orderService;
}

No lookup code! The reference to OrderService is given to our class by the Spring container through the setOrderService() method. With Spring, we never have to trouble ourselves with fetching our dependencies. Instead, our code can focus on the task at hand.

But inversion of control is only one of the techniques that Spring offers to JavaBeans. There's another side to Spring that makes it a viable framework for enterprise development. Let's take a quick look at Spring's support for aspect-oriented programming.

End Notes

1 In this book, Spring was originally called "interface21."

2 The container actually performs other activities involving the life cycle of the bean. But for illustrative purposes, these two lines are sufficient.

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.

4 This assumes that your real-world applications do not involve knights and quests. In the event that your current project does involve knights and quests, you may disregard the next section.

More to Come
The rest of this sample chapter will appear on our Web site starting April 27th.

About the Authors

Craig Walls is a software developer with over 10 years' experience and co-author of XDoclet in Action. He has sucessfully implemented a number of Spring applications. Craig lives in Denton, Texas.

An avid supporter of open source Java technologies, Ryan Breidenbach has been developing Java web applications for the past five years. He lives in Coppell, Texas.

About the Book

A Spring Jump Start.Part.IV_第5张图片 Spring in Action by Craig Walls and Ryan Breidenbach

Published February 2005, Softbound, 472 pages
Published by Manning Publications Co.
ISBN 1932394354
Retail price: $44.95
Ebook price: $22.50. To purchase the ebook go to http://www.manning.com/walls2.
This material is from Chapter 1 of the book.