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.
- before: Run advice before the a method execution.
- after: Run advice after the method execution, regardless of its outcome.
- after-returning: Run advice after the a method execution only if method completes successfully.
- after-throwing: Run advice after the a method execution only if method exits by throwing an exception.
- 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