Why use AspectJ for logging?
Although we already have a few good logging toolkits, such as the standard
Java logging introduced in JDK 1.4 and log4j, we still have to write log
statements everywhere we need logging--and it is not a trivial task. In the
next few sections, we will consider a simple example that will allow us to
examine both conventional and AspectJ-based logging. We will first study the
conventional solution using logging toolkits. This
will help you understand the AspectJ-based solution we will present next, since
it also uses these logging toolkits.
A simple case in point
Consider this simple example of shopping-cart functionality.
For brevity's sake, we will implement only a handful of classes, enough to
allow us to look at various facets of the logging concern. The Item class, in listing 1, models a shopping
item that can be purchased. The Item class
has methods for querying its identifier and price as well as for getting its
string representation.
Listing 1: The Item class: models an item that can be
purchased
public class Item { private String _id;
private float _price;
public Item(String id, float price) { _id = id;
_price = price;
}
public String getID() { return _id;
}
public float getPrice() { return _price;
}
public String toString() { return "Item: " + _id;
}
}
Next, the ShoppingCart class, shown
in listing 2, contains a list and allows us to add and remove items.
Listing 2: The ShoppingCart class: models a shopping cart
import java.util.*;
public class ShoppingCart { private List _items = new Vector();
public void addItem(Item item) { _items.add(item);
}
public void removeItem(Item item) { _items.remove(item);
}
public void empty() { _items.clear();
}
public float totalValue() { // unimplemented... free!
return 0;
}
}
The Inventory class, in listing 3,
models items in the stock. The class contains methods for adding and removing
items.
Listing 3: The Inventory class: models the shop inventory
import java.util.*;
public class Inventory { private List _items = new Vector();
public void addItem(Item item) { _items.add(item);
}
public void removeItem(Item item) { _items.remove(item);
}
}
The next class, ShoppingCartOperator,
shown in listing 4, is a service class that ensures that inventory is kept
up-to-date when items are added to or removed from a shopping cart. This class
allows us to examine logging needs for nested operations.
Listing 4: ShoppingCartOperator: manages the shopping
cart
public class ShoppingCartOperator { public static void addShoppingCartItem(ShoppingCart sc,
Inventory inventory,
Item item) { inventory.removeItem(item);
sc.addItem(item);
}
public static void removeShoppingCartItem(ShoppingCart sc,
Inventory inventory,
Item item) { sc.removeItem(item);
inventory.addItem(item);
}
}
Finally, we implement a class for testing the functionality. As you can see
in listing 5, we simply add several items to the inventory and then add a few
of those items to a shopping cart.
Listing 5: A Test class
public class Test { public static void main(String[] args) { Inventory inventory = new Inventory();
Item item1 = new Item("1", 30); Item item2 = new Item("2", 31); Item item3 = new Item("3", 32); inventory.addItem(item1);
inventory.addItem(item2);
inventory.addItem(item3);
ShoppingCart sc = new ShoppingCart();
ShoppingCartOperator.addShoppingCartItem(sc, inventory, item1);
ShoppingCartOperator.addShoppingCartItem(sc, inventory, item2);
}
}
This collection of classes allows us to understand various logging scenarios
and requirements. As with typical software systems in the initial stages, this example
contains no logging--it is only in later stages that logging becomes an
important concern. Now let's look at logging as it would be implemented in the
conventional way; later we will see how it is implemented in AspectJ.