Webcam Chat QuickBooks Advice international calling cards international phone cards
JavaBeat Certifications Certifications Kits Articles Tutorials Tips QNA Book Store Interview Questions SCJP 1.5 SCJP 1.6 SCWCD 5.0 SCBCD 5.0 SCEA SCJA Feeds
Kaspersky Anti-Virus 2011
Submit Your Blog Feedback Request Article Print Email

Spring 2.5 - Aspect-Oriented Programming(AOP) [Book]

Author : PacktPub
Topic : books spring 
Pages :
Hibernate Books | Spring Books | JSF Books | Java Books
Title : Spring 2.5 - Aspect-Oriented Programming(AOP) [Book]
Publisher : PacktPub
Topic : books
Related : Hibernate, Spring, Struts, ejb
Javabeat : Tips, Java / J2EE Tutorials, Certifications

Chapter 1 introduces the ideas that led to Aspect-Oriented Programming. An overview of main concepts of AOP is used to describe components and features provided by Spring AOP, while a set of concise yet clear examples lets the reader discover what can actually be done with AOP.

Chapter 2 describes in detail the fundamentals of AOP in Spring, presenting interfaces and classes introduced in early 1.x versions of the framework. This chapter shows how to use AOP programmatically, to let the reader discover the basis of Spring AOP and the components that implement Aspect-Oriented Programming in Spring.

Chapter 3 explains how the weaving of AOP components is done using the proxy pattern and JDK or CGLIB implementations. It describes the purpose of proxies and how to use them effectively. Some practical examples show how to use the proxies programmatically, with annotations and with XML; they explain the ProxyFactoryBean and how to make the programmer's work easier with AutoProxy. The chapter describes also some smart techniques on target sources.

Chapter 4 explains how Spring AOP is supported by AspectJ. Configuration activity is made simpler, more flexible and more powerful, thanks to annotations and the syntax of AspectJ on pointcuts (without which those costructs would not be available). All examples show how to use AspectJ with both annotations and XML. The chapter contains practical recipes for specific cases, such as the injection of dependencies on domain objects, the management of aspects' priority, the use of different life cycles for Aspects and how to use Load Time Weaving. The chapter ends with some strategies on how to choose different AOP approaches to fulfil specific requirements.

Chapter 5 describes the design alternatives that can be implemented using AOP. These alternatives are solutions for common requirements: concurrency, caching, and security. Using AOP, they can be achieved in a very elegant and easy way, being at the same time totally transparent for the system where they are applied.

Chapter 6 introduces Domain-Driven Development as a alternative way to design applications. The prototype example presented in this chapter is a typical Three-Layer application, where DDD is used for design and AOP is used to inject the dependencies on domain objects. iBatis is used for persistence to the database.

Chapter 7 completes the prototype application started in Chapter 6, showing the application layer and the user interface. The latter is implemented with Spring MVC using annotations. Integration and unit tests are used to verify the correctness of the classes; DBUnit is used to test persistence classes, while some Mock classes are used to test the UI. The chapter contains the configurations for the prototype infrastructure, including autentication and authorization with Spring Security and the JUnit 4.5 test suite.

Chapter 8 describes the development tools needed to include Spring AOP and AspectJ in the Eclipse IDE. The reader can find here detailed istructions on how to configure Eclipse with the plug-ins for Spring and for the AspectJ Development Tool, and how to install the PostgreSQL database and the Apache Tomcat servlet engine. All installation procedures are described for the three main operating systems: Ubuntu Linux, Apple Mac OS X, and Microsoft Windows XP.

Design with AOP in Spring 2.5

In this chapter, we're going to examine some design decisions that are important for building better applications. In these design decisions, the AOP plays a signifi cant role because it provides smart solutions to common crosscutting problems.

We will look at the following AOP design solutions:

  • Concurrency with AOP
  • Transparent caching with AOP
  • Security with AOP

Designing and implementing an enterprise Java application means not only dealing with the application core business and architecture, but also with some typical enterprise requirements.

We have to defi ne how the application manages concurrency so that the application is robust and does not suffer too badly from an increase in the number of requests. We have to defi ne the caching strategies for the application because we don't want CPU- or data-intensive operations to be executed over and over.

We have to defi ne roles and profi les, applying security policies and restricting access to application parts, because different kinds of users will probably have different rights and permissions. All these issues require writing additional code that clutters our application business code and reduces its modularity and maintainability.

But we have a choice. We can design our enterprise Java application keeping AOP in mind. This will help us to concentrate on our actual business code, taking away all the infrastructure issues that can otherwise be expressed as crosscutting concerns. This chapter will introduce such issues, and will show how to design and implement solutions to them with Spring 2.5 AOP support.

Concurrency with AOP

Concurrency is the system's ability to act with several requests simultaneously, such a way that threads don't corrupt the state of objects when they gain access at the same time.

A number of good books have been written on this subject, such as Concurrent Programming in Java and Java Concurrency in Practice. They deserve much attention, since concurrency is an aspect that's hard to understand, and not immediately visible to developers. Problems in the area of concurrency are hard to reproduce. However, it's important to keep concurrency in mind to assure that the application is robust regardless of the number of users it will serve.

If we don't take into account concurrency and document when and how the problems of concurrency are considered, we will build an application taking some risks by supposing that the CPU will never simultaneously schedule processes on parts of our application that are not thread-safe.

To ensure the building of robust and scalable systems, we use proper patterns. There are JDK packages just for concurrency. They are in the java.util.concurrent package, a result of JSR-166.

One of these patterns is the read-write lock pattern, which consists of is the interface java.util.concurrent.locks.ReadWriteLock and some implementations, one of which is ReentrantReadWriteLock.

The goal of ReadWriteLock is to allow the reading of an object from a virtually endless number of threads, while only one thread at a time can modify it. In this way, the state of the object can never be corrupted because threads reading the object's state will always read up-to-date data, and the thread modifying the state of the object in question will be able to act without the possibility of the object's state being corrupted. Another necessary feature is that the result of a thread's action can be visible to the other threads. The behavior is the same as we could have achieved using synchronized, but when using a read-write lock we are explicitly synchronizing the actions, whereas with synchronized synchronization is implicit. Now let's see an example of ReadWriteLock on the BankAccountThreadSafe object.

Before the read operation that needs to be safe, we set the read lock. After the read operation, we release the read lock.

Before the write operation that needs to be safe, we set the write lock. After a state modifi cation, we release the write lock.


package org.springAOP.chapter.five.concurrent;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public final class BankAccountThreadSafe {
public BankAccountThreadSafe(Integer id) {
this.id = id;
balance = new Float(0);
startDate = new Date();
}
public BankAccountThreadSafe(Integer id, Float balance) {
this.id = id;
this.balance = balance;
startDate = new Date();
}
public BankAccountThreadSafe(Integer id, Float balance, Date start)
{
this.id = id;
this.balance = balance;
this.startDate = start;
}
public boolean debitOperation(Float debit) {
wLock.lock();
try {
float balance = getBalance();
if (balance < debit) {
return false;
} else {
setBalance(balance - debit);
return true;
}
} finally {
wLock.unlock();
}
}
public void creditOperation(Float credit) {
wLock.lock();
try {
setBalance(getBalance() + credit);
} finally {
wLock.unlock();
}
}
private void setBalance(Float balance) {
wLock.lock();
try {
balance = balance;
} finally {
wLock.unlock();
}
}
public Float getBalance() {
rLock.lock();
try {
return balance;
} finally {
rLock.unlock();
}
}
public Integer getId() {
return id;
}
public Date getStartDate() {
return (Date) startDate.clone();
}
…
private Float balance;
private final Integer id;
private final Date startDate;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock rLock = lock.readLock();
private final Lock wLock = lock.writeLock();
}

BankAccountThreadSafe is a class that doesn't allow a bank account to be overdrawn (that is, have a negative balance), and it's an example of a thread-safe class. The final fi elds are set in the constructors, hence implicitly thread-safe. The balance fi eld, on the other hand, is managed in a thread-safe way by the setBalance, getBalance, creditOperation, and debitOperation methods.

In other words, this class is correctly programmed, concurrency-wise. The problem is that wherever we would like to have those characteristics, we have to write the same code (especially the finally block containing the lock's release). We can solve that by writing an aspect that carries out that task for us.


A state modifi cation is execution(void
com.mycompany.BankAccount.set*(*))
A safe read is execution(* com.mycompany.BankAccount.getBalance())
package org.springAOP.chapter.five.concurrent;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.AspectJ.lang.annotation.After;
import org.AspectJ.lang.annotation.Aspect;
import org.AspectJ.lang.annotation.Before;
import org.AspectJ.lang.annotation.Pointcut;
@Aspect
public class BankAccountAspect {
/*pointcuts*/
@Pointcut(
"execution(* org.springAOP.chapter.five.concurrent.BankAccount.
getBalance())")
public void safeRead(){}
@Pointcut(
"execution(* org.springAOP.chapter.five.concurrent.BankAccount.
set*(*))")
public void stateModification(){}
@Pointcut(
"execution(* org.springAOP.chapter.five.concurrent.BankAccount.
getId())")
public void getId(){}
@Pointcut("execution(* org.springAOP.chapter.five.concurrent.
BankAccount.getStartDate()))
public void getStartDate(){}
/*advices*/
@Before("safeRead()")
public void beforeSafeRead() {
rLock.lock();
}
@After("safeRead()")
public void afterSafeRead() {
rLock.unlock();
}
@Before("stateModification()")
public void beforeSafeWrite() {
wLock.lock();
}
@After("stateModification()")
public void afterSafeWrite() {
wLock.unlock();
}
private final ReadWriteLock lock = new
ReentrantReadWriteLock();
private final Lock rLock = lock.readLock();
private final Lock wLock = lock.writeLock();
}

The BankAccountAspect class applies the crosscutting functionality. In this case, the functionality is calling the lock and unlock methods on the ReadLock and the WriteLock. The before methods apply the locks with the @Before annotation, while the after methods release the locks as if they were in the fi nal block, with the @After annotation that is always executed (an after-fi nally advice). In this way the BankAccount class can become much easier, clearer, and briefer. It doesn't need any indication that it can be executed in a thread-safe manner.


package org.springAOP.chapter.five.concurrent;
import java.util.Date;
public class BankAccount {
public BankAccount(Integer id) {
this.id = id;
this.balance = new Float(0);
this.startDate = new Date();
}
public BankAccount(Integer id, Float balance) {
this.id = id;
this.balance = balance;
this.startDate = new Date();
}
public BankAccount(Integer id, Float balance, Date start) {
this.id = id;
this.balance = balance;
this.startDate = start;
}
public boolean debitOperation(Float debit) {
float balance = getBalance();
if (balance < debit) {
return false;
} else {
setBalance(balance - debit);
return true;
}
}
public void creditOperation(Float credit) {
setBalance(getBalance() + credit);
}
private void setBalance(Float balance) {
this.balance = balance;
}
public Float getBalance() {
return balance;
}
public Integer getId() {
return id;
}
public Date getStartDate() {
return (Date) startDate.clone();
}
private Float balance;
private final Integer id;
private final Date startDate;
}

Another good design choice, together with the use of ReadWriteLock when necessary, is using objects that once built are immutable, and therefore, not corruptible and can be easily shared between threads.

Recommended Books

Submit Your Blog Feedback Request Article Print Email

Java / J2EE Tutorials

Spring Framework

Hibernate Framework

JSF Framework

Struts Framework

Java Server Pages(JSP)

Servlets

Java / J2EE Design Patterns

SCJP

SCEA


JavaBeat Website (2004-2009), India
javabeat | advertise | about us | useful resources
Copyright (2004 - 2009), JavaBeat