September 18, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

A Spring Jump Start, Part 2

  • April 27, 2005
  • By Craig Walls and Ryan Breidenbach
  • Send Email »
  • More Articles »
[Editor's Note: This piece picks up where the article A Spring Jump Start left off.]

1.5 Applying aspect-oriented 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.

1.5.1 Introducing AOP

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.



Click here for a larger image.

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 declara-tively to the components that they should affect. This results in components that are more cohesive and that focus on their own specific concerns, completely igno-rant 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 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.

Using AOP, systemwide concerns blanket the components that they impact.

Figure 1.5 Using AOP, systemwide concerns blanket the components that they impact.

1.5.2 AOP in action

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:

package com.springinaction.chapter01.knight;

import org.apache.log4j.Logger;

public class Minstrel {
   Logger song = Logger.getLogger(KnightOfTheRoundTable.class);
   public Minstrel() {}

   public void compose(String name, String message) {
      song.debug("Fa la la! Brave " + name + " did " + message + "!");
   }
}

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

public class KnightOfTheRoundTable {
...
   private Minstrel minstrel;
   public void setMinstrel(Minstrel minstrel) {
      this.minstrel = minstrel;
   }

...

   public HolyGrail embarkOnQuest() throws QuestException {
      minstrel.compose(name, "embark on a quest");
      return quest.embark();
   }
}

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.

Without AOP, a knight must tell his minstrel to compose songs.

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.

Listing 1.11 An aspect-oriented minstrel



Click here for a larger image.

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?

Weaving the aspect

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.

Listing 1.12 Weaving MinstrelAdvice into a knight



Click here for a larger image.

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.





Page 1 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel