| home / programming / spring / 2 | [previous] [next] |
|
|
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?
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.

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

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

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:

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:

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 aspectoriented programming.
While inversion of control makes it possible to tie software components together loosely, aspect-oriented programming enables you to capture functionality that is used throughout your application in reusable components.
Aspect-oriented programming is often defined as a programming technique that promotes separation of concerns within a software system. Systems are composed of several components, each responsible for a specific piece of functionality. Often, however, these components also carry additional responsibility beyond their core functionality. System services such as logging, transaction management, and security often find their way into components whose core responsibility is something else. These system services are commonly referred to as cross-cutting concerns because they tend to cut across multiple components in a system.
By spreading these concerns across multiple components, you introduce two levels of complexity to your code:
The code that implements the systemwide concerns is duplicated across multiple components. This means that if you need to change how those concerns work, you'll need to visit multiple components. Even if you've abstracted the concern to a separate module so that the impact to your components is a single method call, that single method call is duplicated in multiple places.
Your components are littered with code that isn't aligned with their core functionality. A method to add an entry to an address book should only be concerned with how to add the address and not with whether it is secure or transactional.
Figure 1.4 illustrates this complexity. The business objects on the left are too intimately involved with the system services. Not only does each object know that it is being logged, secured, and involved in a transactional context, but also each object is responsible for performing those services for itself.

Figure 1.4 Calls to system-wide concerns such as logging and security are often scattered about in modules where those concerns are not their primary concern.
AOP makes it possible to modularize these services and then apply them declaratively to the components that they should affect. This results in components that are more cohesive and that focus on their own specific concerns, completely ignorant of any system services that may be involved.
As shown in figure 1.5, it may help to think of aspects as blankets that cover many components of an application. At its core, an application is comprised of modules that implement the business functionality. With AOP, you can then cover

Figure 1.5 Using AOP, systemwide concerns blanket the components that they impact.
your core application with layers of functionality. These layers can declaratively be applied throughout your application in a flexible manner without your core application even knowing they exist. This is a very powerful concept.
Let’s revisit our knight example to see how AOP works with Spring. Suppose
that after showing your progress to marketing, they came back with an additional
requirement. In this new requirement, a minstrel must accompany each knight,
chronicling the actions and deeds of the knight in song.5
To start, you create a Minstrel class:

In keeping with the IoC way of doing things, you alter KnightOfTheRoundTable to
be given an instance of Minstrel:

5 Think of minstrels as musically inclined logging systems of medieval times.
There’s only one problem. As it is, each knight must stop and tell the minstrel to compose a song before the knight can continue with his quest (as in figure 1.6). Ideally a minstrel would automatically compose songs without being explicitly told to do so. A knight shouldn’t know (or really even care) that their deeds are being written into song. After all, you can’t have your knight being late for quests because of a lazy minstrel.

Figure 1.6 Without AOP, a knight must tell his minstrel to compose songs.
In short, the services of a minstrel transcend the duties of a knight. Another way
of stating this is to say that a minstrel’s services (song writing) are orthogonal to a
knight’s duties (embarking on quests). Therefore, it makes sense to implement a
minstrel as an aspect that adds its song-writing services to a knight. Probably the
simplest way to create an aspect-oriented minstrel is to change the minstrel class to
be an implementation of MethodBeforeAdvice, as shown in listing 1.11.

As a subclass of MethodBeforeAdvice, the MinstrelAdvice
class will intercept calls to the
target object’s methods, giving
the before() method an
opportunity to do something
before the target method gets
called. In this case, MinstrelAdvice naively assumes that the target object is a
KnightOfTheRoundTable and uses log4j as its mechanism for chronicling the
knight’s actions. As illustrated in figure 1.7, the knight needn’t worry about how
he is being sung about or even that the minstrel is writing the song.

Figure 1.7 An aspect-oriented minstrel covers a knight, chronicling the knight’s activities without the knight’s knowledge of the minstrel.
The knight no longer needs to tell this new aspect-oriented minstrel to sing
about the knight’s activities. In fact, the knight doesn’t even need to know that
the minstrel exists. But how does MinstrelAdvice know that it is supposed to
intercept calls to a Knight?
Notice that there’s nothing about MinstrelAdvice that tells the Minstrel what
object it should sing about. Instead, a Minstrel’s services are applied to a Knight
declaratively. Applying advice to an object is known as weaving. In Spring, aspects
are woven into objects in the Spring XML file, much in the same way that beans
are wired together. Listing 1.12 shows the new knight.xml, modified to weave
MinstrelAdvice into a KnightOfTheRoundTable.

Notice that the id of KnightOfTheRoundTable has changed from knight to
knightTarget and now knight points to a Spring class called ProxyFactoryBean.
What this means is that when the container is asked for a knight object, it will
return an object that intercepts calls to the target KnightOfTheRoundTable object,
giving MinstrelAdvice a shot at handling method calls first. Once MinstrelAdvice is finished, control is returned to KnightOfTheRoundTable to perform the
knightly task.
Don’t worry if this doesn’t make sense yet. We’ll explain Spring’s AOP support in more detail in chapter 3. For now, suffice it to say that even though a knight’s every move is being observed by a minstrel, the knight’s activities are in no way hampered because of the minstrel’s presence.
But Spring’s AOP can be used for even more practical things than composing ageless sonnets about knights. As you’ll see, AOP can be used to provide enterprise services such as declarative transactions and security.
| home / programming / spring / 2 | [previous] [next] |
Created: March 27, 2003
Revised: March 17, 2005
URL: http://webreference.com/programing/spring/2