Understanding Spring AOP

In this Article, we will look into AOP in Spring.

Aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns such as logging, caching, security, transaction management etc.

Let us look into some of key concepts used in AOP.

  • Aspect: This is a module which has a set of APIs providing cross-cutting requirements. An aspect is the combination of advice and joinpoint.
  • Joinpoint: This represents a point in your application where you can plug-in the AOP aspect.
  • Advice: Action taken by the AOP framework at a particular joinpoint. Different types of advice include “around,” “before” and “throws” advice.
  • Pointcut: This is a set of one or more join points where an advice should be executed. You can specify pointcuts using expressions.
  • Target object: Object containing the joinpoint. Also referred to as advised or proxied object.
  • AOP proxy: Object created by the AOP framework, including advice.

Let us look into different types of Advice.

  1. before: Run advice before the a method execution.
  2. after: Run advice after the method execution, regardless of its outcome.
  3. after-returning: Run advice after the a method execution only if method completes successfully.
  4. after-throwing: Run advice after the a method execution only if method exits by throwing an exception.
  5. around: Run advice before and after the advised method is invoked.

Let us look into below code to have a better understanding of things.

Organization.java This is our target class for which we will plugin aspect.

package com.spring.example.bean.aop;

import org.springframework.stereotype.Component;

@Component
public class Organization {

public void name() {
System.out.println(“name API is invoked”);
}

public void ceo() {
System.out.println(“ceo API is invoked”);
}

public void dummy(int i) throws RuntimeException{
System.out.println(“dummy API is invoked”);
if(i==1){
throw new NullPointerException();
}
}

}

AspectTest.java: This is our aspect class where the advices and pointcuts are defined.

package com.spring.example.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.springframework.stereotype.Component;

@Aspect
@Component
public class AspectTest {

@Before(“execution(* com.spring.example.bean.aop.Organization.name())”)
public void beforeAdvice(JoinPoint jp) {
System.out.println(“Executing Before Advice for:” + jp.getSignature());
System.out.println(“Target Class:” + jp.getTarget().getClass());
System.out.println(“Proxy Class:” + jp.getThis().getClass());
}

@After(“execution(* com.spring.example.bean.aop.Organization.name())”)
public void afterAdvice(JoinPoint jp) {
System.out.println(“Executing After Advice for:” + jp.getSignature());
}

@Around(“execution(* com.spring.example.bean.aop.Organization.ceo())”)
public void aroundAdvice(ProceedingJoinPoint jp) throws Throwable {
System.out.println(“Before Method Execution for:” + jp.getSignature());
try {
jp.proceed();
} finally {
}
System.out.println(“After Method Execution for:” + jp.getSignature());
}

@AfterReturning(“execution(* com.spring.example.bean.aop.Organization.dummy(int))”)
public void afterReturningAdvice(JoinPoint jp) throws Throwable {
System.out.println(“After Returning Method Execution for:”
+ jp.getSignature() + ” with args ” + jp.getArgs()[0]);
}

@AfterThrowing(pointcut = “execution(* com.spring.example.bean.aop.Organization.dummy(int))”, throwing = “ex1”)
public void afterThrowingAdvice(JoinPoint jp, Exception ex1) throws Throwable {
System.out.println(“After Throwing Exception for:” + jp.getSignature() + ” with args ” + jp.getArgs()[0] + ” exception :” + ex1);
}

}

TestSpring.java

package com.spring.example.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.spring.example.bean.aop.Organization;
import com.spring.example.config.BeanConfiguration;

public class TestSpring {

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
Organization org = context.getBean(Organization.class);
System.out.println(“——————————————“);
org.name();
System.out.println(“——————————————“);
org.ceo();
System.out.println(“——————————————“);
org.dummy(0);
System.out.println(“——————————————“);
org.dummy(1);
System.out.println(“——————————————“);
context.close();
System.out.println(“——————————————“);
}

}

Output:
——————————————
Executing Before Advice for:void com.spring.example.bean.aop.Organization.name()
Target Class:class com.spring.example.bean.aop.Organization
Proxy Class:class com.spring.example.bean.aop.Organization$$EnhancerBySpringCGLIB$$3bac924
name API is invoked
Executing After Advice for:void com.spring.example.bean.aop.Organization.name()
——————————————
Before Method Execution for:void com.spring.example.bean.aop.Organization.ceo()
ceo API is invoked
After Method Execution for:void com.spring.example.bean.aop.Organization.ceo()
——————————————
dummy API is invoked
After Returning Method Execution for:void com.spring.example.bean.aop.Organization.dummy(int) with args 0
——————————————
dummy API is invoked
After Throwing Exception for:void com.spring.example.bean.aop.Organization.dummy(int) with args 1 exception :java.lang.NullPointerException
Exception in thread “main” java.lang.NullPointerException
at com.spring.example.bean.aop.Organization.dummy(Organization.java:19)
at com.spring.example.bean.aop.Organization$$FastClassBySpringCGLIB$$b4f54ae5.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
at com.spring.example.bean.aop.Organization$$EnhancerBySpringCGLIB$$3bac924.dummy()
at com.spring.example.test.TestSpring.main(TestSpring.java:21)

Let us look into some of the important information which are available via the JoinPoint object.

  • Object getThis(): Returns the currently executing object.
  • Object getTarget(): Returns the target object.
  • Object[] getArgs(): Returns the arguments at this join point
  • Signature getSignature(): Returns the signature at the join point.
  • SourceLocation getSourceLocation(): Returns the source location corresponding to the join point.

Related Article

Very Important Spring Topic Links

Leave a Reply

Your email address will not be published. Required fields are marked *