Tuesday, October 11, 2011

Aspect Oriented Programming (AOP) using AspectJ

Cross cutting concerns is set of behaviours needed by the conceptual section s of the program. An example of the cross cutting concerns is Logging.
AOP separates the cross cutting concerns from the functional requirements hence increasing the modularity of the code and making it easier to maintain and decreasing the complexity.
AspectJ is the aspect oriented extension for the Java Programming Language.
Following are the terminologies used in AOP
1.        Aspect - General feature we want to apply globally to your application (ex. Logging , transaction Management)
2.       Advice - A chunk of code that is invoked during program execution
3.       Joinpoint - A single location in the code where an advice should be executed  
4.        Pointcut - A pointcut is a set of many joinpoints where an advice should be executed
5.        Targets/Target Objects - The objects you want to apply an aspect or set of aspects to
6.       Introduction - This is the ability to add methods to an object
Different Types of advices in AspectJ are:
1.       Before advice:  Before advice executes before the execution of the advised join point. The  syntax of this advice is  before(args) : pointcut_expression {}
2.       After advice:  After advice executes after the execution of a join point. The  syntax of this advice is  after(args) returning() : pointcut_expression {}
3.       Around advice:  Around advice surrounds join points i.e. it can execute before and after the join points execution. The syntax of this advice is  around(args) : pointcut_expression {}. Responsibility when using an around advice is calling   the join point by using the proceed() method.
4.       After Throwing: This advice will be called when an advised join point throws an exception. The  syntax of this advice is  after(args) throwing() : pointcut_expression {}
 Eclipse IDE provides the AspectJ development tools plugin (available in Eclipse MarketPlace) .

This is an intuitive way to work with AspectJ. After installing the AspectJ Plugin we can create an Aspect Project.
An Aspect can be created from the Eclipse menu Just like the way we create a Class or an interface.
AspectJ defines various mechanisms of aspect Association which defines the ways to associate Aspect instances:
1.       Singleton (default) : This type of association creates one instance of the aspect for an aspect type.
2.       Per object: a new aspect instance with each execution or target objects. This is enabled for an aspect by specifying perthis(pointcut_expression)  on an Aspect.
3.       Per control-flow : Consider a transaction-management aspect. You need to maintain the transactional resource (JDBC connection, Hibernate session) from the point at which the transaction starts until it ends. The per-control-flow aspects offer a possibility of associating an aspect instance with each control flow associated with a join point. .This is enabled for an aspect by specifying percflowbelow(pointcut_expression) on  an Aspect.
4.       Per type : Associating an aspect instance with the type (class, interface, or aspect) is similar to object association, except the aspect instance is associated with the class instead of objects. This is enabled for an aspect by specifying pertypewithin(type_pattern) on  an Aspect.
 
The Example i will be using for explaining consists of following classes:
1.       Employee
2.       Department
3.       EmployeeInfo
4.       App
Where Employee and Department are the beans and EmployeeInfo contains some business methods using Employee and Department.

I’m not putting whole code  rather i  will mention the  snippets from the code  however  for your reference you can download it from here
And the Aspects are:
1.       LoggingAspect – defines the before, Around and After return advices.
public aspect LoggingAspect {
      pointcut Logging() :execution(* EmployeeInfo.*(..));
     
/*
 * before Advice will be called before the method call.
*/
before() : Logging() {
System.out.println("Inside Before Advice before calling-->" +thisJoinPointStaticPart.getSignature());
             
      }
     
/*
 * around Advice will be called before  and after the method call but remember for we need explicitly proceed the target method usine proceed().
*/

      Object around() : Logging() {
System.out.println("inside Around Advice before Proceed to method -->"+thisJoinPointStaticPart.getSignature());
System.out.println("method Arguments are-->"+thisJoinPoint.getArgs()[0]);
      Object ret = proceed();
System.out.println("inside Around Advice after Proceed from method");
      return ret;
           
      }
   
/*
*after advice will be called after the method called
*/
       after() returning() :Logging(){
             System.out.println("******Inside After Returning Advice ********");
       }
}

2.       InterTypeDeclarationAspect – defines the aspect for introduction feature of AOP. In the below aspect i will be adding an attribute to Employee class named  employeeManagerName. This attribute will have its getter and setter as defined in aspect and  also a business method printEmployeeManger.
public aspect InterTypeDeclarationAspect {
  /*
   * new attribute employeeManagerName to employee
   */
   private String Employee.employeeManagerName ;
   /*
    * getter of employeeManager
    */
   public String Employee.getEmployeeManger()
   {
      return   employeeManagerName;
   }
   /*
    * setter of employeeManager
    */
   public void Employee.setEmployeeManger(String managerName)
   {
          employeeManagerName = managerName;
   }
   /*
    * business Method on employeeManager
    */
   public void EmployeeInfo.printEmployeeManger(Employee employee)
   {
System.out.println("Employee Manager name is-->"+employee.getEmployeeManger());
   }
}

Let’s test these Aspects :
Following is the section of code which  will be executed by App class:
public static void main(String[] args) {
Department itDepartment = new Department("Information Tecchnology" , "123");
            Employee employee = new Employee("Jim", "NY", itDepartment );
            /*
* After creating InterTypeDeclarationAspect aspect i  the  *setter and getters of employee
             * Manger
             */
            employee.setEmployeeManger("Tim");
           
            EmployeeInfo employeeInfo  = new EmployeeInfo();
           
            employeeInfo.printEmployeeDetails(employee);         
}

Hence , a call to “printEmployeeDetails” will internally call “printEmployeeDepartmentDetails” and also “printEmployeeManger” as provided by aspect.

Inside EmployeeInfo I have following code in place which call a private method and public method. All the 3 advices will be executed  for 3 methods.

public class EmployeeInfo {
       public void printEmployeeDetails(Employee employee)
       {
System.out.println("Employee Name-->"+employee.getName()+" Employee Address is-->"+employee.getAddress());
            printEmployeeDepartmentDetails(employee);
       }
       private void  printEmployeeDepartmentDetails(Employee employee)
       {
System.out.println("Employee Named --> "+employee.getName()+" belongs to department-->" +employee.getEmployeeDepartment().getDepartmentName());
             printEmployeeManger(employee);
       }
}

Following it the output when i Run thic code :

Inside Before Advice before calling-->voidcom.aspectJ.sample.EmployeeInfo.printEmployeeDetails(Employee)

inside Around Advice before Proceed to method -->void com.aspectJ.sample.EmployeeInfo.printEmployeeDetails(Employee)

method Arguments are-->com.aspectJ.sample.Employee@157f0dc

Employee Name-->Jim Employee Address is-->NY ( this is code inside method printEmployeeDetails)

Inside Before Advice before calling-->void
com.aspectJ.sample.EmployeeInfo.printEmployeeDepartmentDetails(Employee)
inside Around Advice before Proceed to method -->void com.aspectJ.sample.EmployeeInfo.printEmployeeDepartmentDetails(Employee)
method Arguments are-->com.aspectJ.sample.Employee@157f0dc

Employee Named --> Jim belongs to department-->123 (this is code inside printEmployeeDepartmentDetails)

Inside Before Advice before calling-->void com.aspectJ.sample.EmployeeInfo.printEmployeeManger(Employee)
inside Around Advice before Proceed to method -->void com.aspectJ.sample.EmployeeInfo.printEmployeeManger(Employee)

Employee Manager name is-->Tim(this is the code inside printEmployeeManger)

inside Around Advice after Proceed from method-->void com.aspectJ.sample.EmployeeInfo.printEmployeeManger(Employee)
******Inside After Returning Advice ******** from method -->void com.aspectJ.sample.EmployeeInfo.printEmployeeManger(Employee)

inside Around Advice after Proceed from method-->void com.aspectJ.sample.EmployeeInfo.printEmployeeDepartmentDetails(Employee)
******Inside After Returning Advice ******** from method -->void
com.aspectJ.sample.EmployeeInfo.printEmployeeDepartmentDetails(Employee)

inside Around Advice after Proceed from method-->void com.aspectJ.sample.EmployeeInfo.printEmployeeDetails(Employee)
******Inside After Returning Advice ******** from method -->void com.aspectJ.sample.EmployeeInfo.printEmployeeDetails(Employee)

For build process using Ant build.xml , you can access my  blog.

2 comments:

Anubhav said...

Makes sense and looks very similar to design patterns...good article overall

e-sign act said...

Hi there! glad to drop by your page and found these very interesting and informative stuff. Thanks for sharing, keep it up!