Skip to main content

Spring AOP and AspectJ Framework Integration

This post gives us the basic understanding for the Spring AOP and AspectJ Framework Integration.
AOP stands for Aspect Oriented Programming technique where modularity within an application is achieved via Aspects unlike some other programming techniques like OOPs where the unit of modularity is class.
AOP can be easily used within OOPs and gives us an extra edge for creating Enterprise Applications that contains transaction management,logging,security checks and authentications.
AOP breaks the programming logic into parts called concerns which should be centralized in order to help us to maintain and reuse the code.
For ex:
Say, we need to build an application where we have to keep logging the actions performed throughout the code using log() method.
Approach 1:
class Demo
{
        method1();
        log();
        method2();
        log();
        method3();
        log();
        method4();
        log();
        method5();
        log();
        method6();
        log();
}
The above approach would be the worst approach to do the above task as :
  1. We need to place log() after every action and if my Applications is large and contains thousands of actions than this would be a tedious task.
  2.  Also if in future we have to remove the logging feature after a few actions we would have to change the whole code as this could not be done at run-time.
Here , AOP comes into place to overcome the shortcomings by centralizing the concern  of logging after every action using AOP constructs.
AOP Constructs:
  1. Aspect : An aspect is a class that holds the centralizing concern which can be used throughout the application for logging,transaction management, security and authentication any number of times. An Aspect class is defined using @Aspect annotation.
  2. Join Point : A Join Point is the point of application which joins the business logic of the application with the centralized concerns. Spring only supports method execution as a Join point i.e. before or after execution of a method(action) the business logic can join to a concern as required.
  3. PointCut : A PointCut is an EL(expression language) that is used to define the condition when the flow of execution passes from the business logic to the concerns and then back to the business logic. A PointCut expression is defined as @PointCut annotation .
  4. Advice : Advice will be the actual method/action that has to be performed i.e. logging, authentication,messaging etc. Advices are defines on the basis of below annotations
    • @Before:It is used to call concern before actual method of business code.
    • @After:It is sued to call concern after actual method of business code.
    • @AfterReturning: It is used to call concern after the actual method successfully returns a value.
    • @AfterThrowing : It is used to call concern in case the actual method throws an exception.
PointCut:
Lets focus on first defining the expression which controls the execution of any advice .
We use @PointCut annotation for the same and use the below syntax :
@PointCut("execution(accessmodifies/returntype fullmethodname(..))").
Examples:
1.The below PointCut will check for a public method display of class com.java.aop.spring.Application .
         @PointCut("execution(public com.java.aop.spring.Application.display(..))")
2.The below PointCut will check for any public method starting with get of  class com.java.aop.spring.Application.
         @PointCut("execution(public com.java.aop.spring.Application.get*(..))")
3.The below PointCut will check for any method having return type as int and name as finalOutput of  class com.java.aop.spring.Application .
         @PointCut("execution(int com.java.aop.spring.Application.finalOutput*(..))")
4.The below definition can also be given where we define the name of the PointCut expression as a method and can use this method name throughout the program so that we dont have to re-write the Expression again and again .
        @PointCut("execution(public com.java.aop.spring.Application.display(..))")
            public void pointCut(){}
Please refer to the AfterReturning Advice example for the syntax.

Lets see each Advice feature in detail.
Before Advice:
Suppose you need specific logging to be done before a particular method in the Application code is executed. Before Advice is the key to pick.
For example:
The below Advice will be called before display method as defined below.
   @Before(@PointCut("execution(public com.java.aop.spring.Application.display(..))"))
           void beforeAdvice(JoinPoint jp)
            {
             System.out.println("Before the function "+jp.getSignature());
             }
After Advice:
Suppose you need specific logging to be done after a particular method in the Application code is executed. After Advice is the key to pick.
For example:
@After(@PointCut("execution(public com.java.aop.spring.Application.display(..))"))
           void afterAdvice(JoinPoint jp)
            {
             System.out.println("After the function "+jp.getSignature());
             }

AfterReturning Advice:
Suppose you need specific logging to be done after a particular method in the Application code is executed and returned a value "result". AfterReturning Advice is the key to pick.
You can use the returned value inside your advice method.
For example:
@PointCut("execution(public com.java.aop.spring.Application.getName(..))")
public void pointCut(){}
          @AfterReturning(pointcut="pointCut()" , returning="result")
           void afterReturningAdvice(JoinPoint jp,Object result)
            {
             System.out.println("After Returning from the function "+jp.getSignature());
             System.out.println("Retruned Value is "+result);
             }
AfterThrowing Advice:
Suppose you need specific logging to be done after a particular method in the Application code is executed and thrown a exception "error". AfterThrowing Advice is the key to pick.
You can use the thrown exception inside your advice method.
For example:
@PointCut("execution(public com.java.aop.spring.Application.display(..))")
public void pointCut(){}
          @AfterThrowing(pointcut="pointCut()" , throwing="error")
           void afterReturningAdvice(JoinPoint jp,Throwable error)
            {
             System.out.println("After throwing from the function "+jp.getSignature());
             System.out.println("Thrown Exception is"+error.getMessage());
             }
Around Advice:
Suppose you need specific logging to be done before and after a particular method in the Application code is executed . Around advice is the key to pick.
For example:
@PointCut("execution(public com.java.aop.spring.Application.display(..))")
public void pointCut(){}
          @Around("pointCut()")
           void aroundAdvice(ProceedingJoinPoint pjp) throws Throwable
            {
             System.out.println("Before the function "+jp.getSignature());
             Object obj=pjp.proceed();
             System.out.println("After the function "+jp.getSignature());
             }

Simple Program for Understanding the AOP Concept in Spring Framework
Application Class
package aop;
public class Application {
        int appId;
        String appName;
        public void display()
        {
                System.out.println("AppId:"+appId+" AppName"+appName);
        }
        public int getAppId() {
                return appId;
        }
        public void setAppId(int appId) {
                this.appId = appId;
        }
        public String getAppName() {
                return appName;
        }
        public void setAppName(String appName) {
                this.appName = appName;
        }
        public void ExceptionMethod() throws Exception
        {
                if(appId<1000)
                {
                        throw new Exception("AppId not valid");
                }
                }
        }
AppAspect Class:
package aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AppAspect {
        @Pointcut("execution(* aop.Application.display(..))")
        public void pointCutDisplay(){}
     
        @Pointcut("execution(* aop.Application.get*(..))")
        public void pointCutGetter(){}
       
        @Pointcut("execution(* aop.Application.Exception*(..))")
        public void pointCutException(){}
   
        @Before("pointCutDisplay()")
        void beforeMethod(JoinPoint jp)
        {
                System.out.println("Advice Before Display Method");
                System.out.println(jp.getSignature());
                System.out.println("Ending Before Advice");
        }
@After("pointCutDisplay()")
void afterMethod(JoinPoint jp)
{
        System.out.println("Advice After Display Method");
        System.out.println(jp.getSignature());
        System.out.println("Ending After Advice");
}
@AfterReturning(pointcut="pointCutGetter()",returning="result")
void afterReturningMethod(JoinPoint jp,Object result)
{
        System.out.println("Advice After Returning Getter Method");
        System.out.println(jp.getSignature());
        System.out.println("Returned Value"+result);
        System.out.println("Ending Advice");
}
@AfterThrowing(pointcut="pointCutException()",throwing="error")
void afterThrowingMethod(JoinPoint jp,Throwable error)
{
        System.out.println("Advice After Throwing Exception");
        System.out.println(jp.getSignature());
        System.out.println("Thrown Message Value"+error.getMessage());
        System.out.println("Ending Advice");
}
@Around("pointCutDisplay()")
Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable
{
        System.out.println("Around Advice before Method");
        Object obj=pjp.proceed();
        System.out.println("Around Advice after Method");
        return obj;
}}
AppClient Class:
package aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppClient {
        public static void main(String[] args)  {
                // TODO Auto-generated method stub
                ApplicationContext applicationContext=new ClassPathXmlApplicationContext("aopApplicationContext.xml");
                Application app=(Application)applicationContext.getBean("application");
                app.display();
                app.getAppId();
                app.getAppName();
                try {
                        app.ExceptionMethod();
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        System.out.println(e.getMessage());
                }       
        }
}
aopApplicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:aop="http://www.springframework.org/schema/aop"   
       xsi:schemaLocation="http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans.xsd   
       http://www.springframework.org/schema/aop   
       http://www.springframework.org/schema/aop/spring-aop.xsd">  
    <bean id="application" class="aop.Application">
        <property name="appId" value ="999"></property>
        <property name="appName" value="Tic-Tac-Toe"></property>
    </bean>
    <bean id="appAspect" class="aop.AppAspect">        
    </bean>
    <aop:aspectj-autoproxy />
    </beans>
Output:

Please feel free to reach out in case of any query , errors or suggestions.

!!Comment, Share and Follow !!

Comments

Popular Posts