AOP Tutorial Spring Aspect Oriented Programming


Generally, a Java program includes the business application logic along with extra other services code for database access, cluster integration, proxy maintenance, logging, security, transaction integrity, authentication, performance, multithread safety, error checking, resource pooling, storage management etc. These extra codes (other than actual business application logic) are known as services because they serve the main application with different functionalities (purposes). All these services are known as concerns (literal meaning: unease or worry) and more precisely, in AOP style, crosscutting concerns. For example, logging and security code cross cuts (interweaves) the actual logic and thereby readability of main code decreases due to clumsiness and thereby maintenance becomes difficult. Here comes AOP (Aspect Oriented Programming) to the rescue. AOP separates code of these crosscutting (logging and security etc.) concerns from the core business logic (aspect literal meaning: piece, part or phase). AOP separates the code into aspects (pieces). The result of AOP is more clean code easier to understand, less chances of occurring errors, ease of maintenance and easy to design and implement. AOP complements OOP and makes Java code robust and increases productivity.

Now read slowly this AOP Tutorial, especially understand the AOP terminology.

To put all the above in a simple way, AOP is the style of applying services like transaction management, caching for performance, resource management etc to the business logic. These services are known as crosscutting concerns. These services may run across many modules of the project and cross cuts the actual logic.

Advantages of AOP

The crosscutting concerns may be placed in many modules and difficult to maintain. AOP modularize the concerns with loose coupling.

Spring framework main strength is AOP. AOP makes Spring as a robust and flexible framework.

Modularizing crosscutting concerns: AOP modularize each concern resulting minimal coupling. As each concern is implemented separately, code clutter is reduced and thereby readability and reusability increases.

  1. Adding newer concerns: Since AOP reduces strong coupling, new concerns can be developed and added to the existing.
  2. Easy to design and handle: As each concern is separate, it is easy to design by an architect and later code development and maintenance are at ease.
  3. AspectJ: It is an AOP implementation for Java applications. AspectJ is a free AOP implementation for Java developed by Xerox PARC.

The fundamental unit (unit of modularity) in AOP is aspect similar to a class in OOP Java. But Spring comes with its own implementation of AOP (ofcourse, with a few less features than AspectJ). Spring programmer need not use AspectJ until and unless he requires more features of AOP.

AOP Terminology

AOP completely changes the architect’s thinking of project design from object-oriented to aspect-oriented. Aspect-oriented programming is the most demanded today, especially, in Java enterprise development. Spring dependency injection in combination with AOP made enterprise application development easier (if you have done with EJB earlier, you might know its degree of complexity). Like any other, AOP also comes with its own jargon of terms like aspect, concern, joinpoint, pointcut etc. Defining them right now makes very difficult to understand because they differ narrowly in their meaning. For this reason, we will go through some code example without knowing the terms and then apply them to the code and define them (means, you are using them without knowing them). That is, after a practical example, let us define the terms. It is the better way, else, it is difficult to understand and finally you may leave learning AOP and Spring (but you cannot, your job demands).

Let us see the code snippet as per OOP methodology without using AOP environment.

public class MoneyTransfer
{
  public String debit(int sourceAccount, double transferAmount) 
  {
    sourceAmount = sourceAmount - transferAmunt; 
    return "amount debited";
  }
  public String credit(int targetAccount, double transferAmount) 
  {
    targetAmount = targetAmount + transferAmunt; 
    return "amount credited";
  }
  public void cleanUp()
  {
      // close JDBC connection
      //  close accounts
  }
}

The above code snippet illustrates simple money transfer between two accounts. For the above code, let us add a small piece of security for transferring money between two accounts. The security is that no person in the bank can transfer until and unless he has manager privileges. Let us add this privilege to the above code.

public class MoneyTransfer
{
  public String debit(int  sourceAccount, double transferAmount) 
  {
    Clerk c1 = new Clerk("S N Rao");
    if(c1.getRole().equals("Manager")
    {
      sourceAmount = sourceAmount - transferAmunt; 
      return "amount debited";
    }
  }
  public String credit(int  targetAccount, double transferAmount)  
  {
    Clerk c1 = new Clerk("S N Rao");
    if(c1.getRole().equals("Manager")
    {
      targetAmount = targetAmount + transferAmunt; 
      return "amount credited";
    }
  }
  public void cleanUp()  
  {
    //  close accounts
  }   
}

Let us imagine, the Clerk "S N Rao" is affecting the money transfer operation in the bank. The code is additionally added with if condition to ensure the fund transfer. Let us add some more code that gives the advantage of logging (to know the flow of control and facility for debugging) and transaction management (to ensure safe and successful transaction operation). You might understand by this time that we are adding concerns one by one to the main stream code.

public class MoneyTransfer   
{
  public String debit(int  sourceAccount, double transferAmount)  
  {
    Clerk c1 = new Clerk("S N Rao");
    if(c1.getRole().equals("Manager")
    {
      logger.details("Money debiting started");
      Transaction tx = session.openTransaction();
      tx.begin();
      
      sourceAmount = sourceAmount - transferAmunt; 
      tx.commit();
      logger.details("Money debited successfully");
      return "amount debited";
    }
    else
    {
      tx.rollback();
      logger.details("Money debiting failed");
    }
  }                                            // same way apply for credit() method also as follows
   
   public String credit(int  targetAccount, double transferAmount) 
   {
     Clerk c1 = new Clerk("S N Rao");
     if(c1.getRole().equals("Manager")
     {
       logger.details("Money crediting started");
       Transaction tx = session.openTransaction();
       tx.begin();
       targetAmount = targetAmount + transferAmunt; 
       tx.commit();
       logger.details("Money credited successfully");
       return "amount credited";
     }
     else
     {
       tx.rollback();
       logger.details("Money crediting failed");
     }
   }
   public void cleanUp()  
   {
     // close JDBC connection
     //  close accounts
   }
}

Writing the extra code (known in AOP as concern)like this is not at all advantages. The main problem is for every extra coding it is forcing the method to change complete code. Now we can say, the extra code (concern) cross cuts the actual code in two places (debit and credit). Adding the code without testing, bug fixing and not undergoing SDLC (Software development life cycle) is against to the software designing principles. The problem becomes very serious, especially, in big projects where a single line of code change may affect lot of other modules due to dependencies. Moreover, the code becomes clumsy and actual code of debiting and crediting becomes invisible.

Problem solving with AOP – AOP Introduction

If you observe the code, it reveals many facts. The class MoneyTransfer’s core logic is debiting and crediting and apart it is using the services like logging, role checking and transaction management. Let us write the services in pseudo-code fashion to understand better.

public String credit(int sourceAccount, double transferAmount)
{
// Security (role) checking
// Logging information
// Transaction management
// Core (business) logic
}
public String debit(int targetAccount, double transferAmount)
{
// Security (role) checking
// Logging information
// Transaction management
// Core (business) logic
}

The above pseudo-code makes clear that services like security management, logging and transaction management are not part of the actual business logic of debiting and crediting. It does not mean that they are not needed and infact, must be added to make 100% successful transaction. In AOP terminology, these services are known as concerns whose code cross-cuts the actual business logic that may sweep between modules. This is known as cross-cutting concerns. The original idea of AOP is to isolate and modularizing the cross-cutting code from the main stream so that it can be put wherever and whenever wanted. And moreover, the code will be very clear and easier to understand and debug. In the above code, the same concerns code is put twice in two methods. AOP comes with its own techniques of gluing the concern code with the actual code (we learn later). cleanUp() method is another place where the concept of closing database connections or sessions can be done.

Now it is the time to go through the AOP jargon.

1. Aspect

Every cross-cutting concern comes with some functionality like error checking or logging etc. In AOP terminology, the concerns are known as aspects. That is, every aspect has got some functionality (output or purpose) cross-cutting over multiple objects spread between many modules. The aspects in the above code are security (role) checking, logging information and transaction management. We can still understand that an aspect comprises of a chunk of code supposed to perform some functionality for which it is meant to be.

2. Joinpoint

So now we have aspect code and our business logic code (core code or main stream code). As an aspect is a separate entity (class) it can be added at any point in the core code where you feel fit. This point is known as joinpoint (to say, an execution point). So, what is joinpoint? Joinpoint is a point (place) in the core code where an aspect can be applied (placed). In the above code, there are two joinpoints – one debit() method and the other credit() method. Generally joinpoints are methods. AspectJ, another implementation of AOP, supports fields also. That is, in AspectJ (remember, we are using Spring AOP and not AspectJ AOP) an aspect can be added at field level also.

3. Pointcut

It does not mean that each aspect should be applied at every joinpoint. You can be choosy as per your requirement. At a single joinpoint, one aspect or many aspects (a set of aspects) can be applied like, as in our example, logging and transaction management, both in a single method. Aspect and main code are two different entities. They are glued (or mapped or connected) by a pointcut. A pointcut defines at what joinpoint what aspect (or set of aspects) should be applied. Other way to say, a pointcut binds a particular aspect to a particular joinpoint. In our code, the pointcut says the aspects of logging and transaction management should be applied at joinpoints of debit() and credit() methods.

Other way to say is you have many aspects (a set of aspects) and many joinpoints (a set of joinpoints). What aspect should be applied at what joinpoint is given by pointcut.

Now I am sure that you are clear about cross-cutting concern, aspect, joinpoint and pointcut. Let us go for some more terminology.

4. Advice

Very important word of AOP terminology is advice. Aspect is a concept but does not represent the code. You can imagine an aspect like an interface which does not represent code. You require an implementation class for the interface where you can fill the code for all the abstract methods of the interface. It is what exactly advice (implementation class) is for an aspect (interface).

Advice contains code, contains actual functionality, contains methods where you can fill the methods with the cross-cutting code. Advice provides concrete code. So, advice comes with many methods and the programmer can decide the advice when to apply the method; is it before the actual method execution or after or both before and after? Advice comes with predefined callback methods where you can put the cross-cutting code. Being callback, they are called implicitly by the AOP container. In the configuration mapping file tell the container when to apply – before or after returning etc.

5. Introduction

Spring permits to add our own interfaces, to do with advised objects, with implementation subclasses of our choice. For example in the later programs, I have introduced, ES.java interface with some generic methods and this interface is implemented in EmpService.java. Introduction is AspectJ term (not supported by Spring) for inter-type declaration.

6. Target object

It is the object where an advice can be applied (for this reason known as advised object). It may be a MoneyTransfer object as in the above code.

7. AOP Proxy

In reality, the AOP container does not call the target object directly. Instead it creates implicitly a proxy of target class and calls the proxy class methods. It means that the target object is nothing but internally the proxy object. So you are calling, indirectly, a proxy object (or applying advices on a proxy object).

The main idea for which AOP is developed is to separate the business code from the services code and to avoid cross-cutting. This separation increases the readability and facilitates faster debugging. As the concerns code is externalized, there must be somewhere else a mapping between the two. We do it in the configuration XML file, applicationContext.xml.

Conclusion

As per the code and pseudo-code you have seen earlier, following definitions can be derived.

Cross-cutting concern: Examples of concerns are transaction management, logging, error checking and authentication etc. The code of these concerns cross-cuts (interweaves) the main business logic. Writing the main code along with the concern code is old style as the code finally becomes unreadable and difficult to debug. The new style is AOP where we write the cross-cutting concern code separately (as separate entity) and add to the main code wherever required.

  1. Aspect: A concern in AOP terminology is called as aspect. So, aspect is a concern that may deal with transaction management or logging etc. Aspect modularizes the concern.
  2. Joinpoint: A joinpoint is the place where you can include the aspect; a place in the execution of a program.
  3. Pointcut: A program may comprise of many joinpoints and many aspects. Both are different sets (entities) no way related. A pointcut defines which aspect should be applied at what joinpoint. Or, a pointcut maps an aspect with a particular joinpoint. How a pointcut maps? A pointcut comes with an expression like a regular expression (of Pearl fame and supported by JDK 1.5) with a matcher to match a joinpoint. This pointcut expression we see later.
  4. Advice: Advice is simply a method stuffed with aspect code. Advice provides concrete implementation for the aspect. Think aspect as an interface and advice is implementation class. Aspect is just a concept like authentication and advice contains code of authentication. In practical, the AOP container executes the advice at a particular joinpoint. Many a times, one joinpoint may require multiple advices (like the methods that may give transaction management and logging etc). Finally, advice represent methods that are executed at runtime at joinpoints either before the actual (core) method is called or after or both. Programmer uses advice to take an action at a joinpoint.

Pass your comments of how far I am successful to bring the AOP concepts to you in this AOP Tutorial.

2 thoughts on “AOP Tutorial Spring Aspect Oriented Programming”

  1. Sir,

    How can you be so clear where even a layman can understand.

    You are really a gem who suits the word ‘TRAINER’

    Hats off.

    Rajeswari K

Leave a Comment

Your email address will not be published.