3.Spring AOP - AspectJ
Spring Framework recommends you to use Spring AspectJ AOP implementation over the Spring 1.2 old style dtd based AOP implementation because it provides you more control and it is easy to use.
There are two ways to use Spring AOP AspectJ implementation:
- By annotation
- By xml configuration
1. AspectJ –By Annotations
Common AspectJ annotations
-
@Aspect declares the class as aspect.
-
@Pointcut declares the pointcut expression.
-
@Before – Run before the method execution
-
@After – Run after the method returned a result
-
@AfterReturning – Run after the method returned a result, intercept the returned result as well.
-
@AfterThrowing – Run after the method throws an exception
-
@Around – Run around the method execution, combine all three advices above.
Pointcut: Pointcut is an expression language of Spring AOP.The @Pointcut annotation is used to define the pointcut. We can refer the pointcut expression by name also. Let’s see the simple example of pointcut expression.
@Pointcut("execution(* Operation.*(..))")
private void getData() {}
1.Student.java
: Normal bean, with few methods, StudentImpl its implementation class
//file :Student.java
public interface Student {
void addStudent();
String studentReturnValue();
void studentThrowException() throws Exception;
void studentAround(String name);
}
//file :StudentImpl.java
public class StudentImpl implements Student {
@Override
public void addStudent() {
System.out.println("Satya : new Student Added");
}
@Override
public String studentReturnValue() {
return "Return Student: satya";
}
@Override
public void studentThrowException() throws Exception {
System.out.println("studentThrowException() is running ");
throw new Exception("Student Error");
}
@Override
public void studentAround(String name) {
System.out.println("studentAround() is running, args : " + name);
}
}
2.SpringConfig.xml: put <aop:aspectj-autoproxy >
, and define Aspect &
normal bean.
<beans>
<aop:aspectj-autoproxy />
<bean id="studentOb" class="StudentImpl" />
<!-- Aspect -->
<bean id="logAspect" class="LoggingAspect" />
</beans>
3.Write Aspect class to Apply asepcts & define PointCut’s where to apply those aspects
AspectJ -pointcuts” is used to declare which method is going to intercept.
// LoggingAspect.java
@Aspect
public class LoggingAspect {
@Before("execution(* addStudent(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("******");
}
@After("execution(* addStudent(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("logAfter() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("******");
}
@AfterReturning(
pointcut = "execution(* studentReturnValue(..))",
returning= "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("logAfterReturning() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("Method returned value is : " + result);
System.out.println("******");
}
@AfterThrowing(
pointcut = "execution(* studentThrowException(..))",
throwing= "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
System.out.println("logAfterThrowing() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("Exception : " + error);
System.out.println("******");
}
@Around("execution(* studentAround(..))")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("logAround() is running!");
System.out.println("method : " + joinPoint.getSignature().getName());
System.out.println("arguments : " + Arrays.toString(joinPoint.getArgs()));
System.out.println("Around before is running!");
joinPoint.proceed();
System.out.println("Around after is running!");
System.out.println("******");
}
}
4.Test Class to test the Application
public class AspectJTestApp {
public static void main(String[] args) throws Exception {
Resource res = new ClassPathResource("SpringConfig.xml");
BeanFactory factory = new XmlBeanFactory(res);
Student s = (Student) factory.getBean("studentOb");
s.addStudent();
s.studentReturnValue();
s.studentAround("SATYA");
s.studentThrowException();
}
}
================ output ================
Exception in thread "main" Satya : new Student Added
studentAround() is running, args : SATYA
studentThrowException() is running
java.lang.Exception: Student Error
at StudentImpl.studentThrowException(StudentImpl.java:18)
at AspectJTestApp.main(AspectJTestApp.java:20)
2. AspectJ –By XML Configuration
Let’s see the xml elements that are used to define advice.
-
< aop:before> = @Before
-
< aop:after> = @After
-
< aop:after-returning> = @AfterReturning
-
< aop:after-throwing> = @AfterThrowing
-
< aop:after-around> = @Around
In this example Student, StudentImpl,LoggingAspect java files are same as Annotation Example
@Aspect
public class LoggingAspect {
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("******");
}
public void logAfter(JoinPoint joinPoint) {
System.out.println("logAfter() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("******");
}
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("logAfterReturning() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("Method returned value is : " + result);
System.out.println("******");
}
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
System.out.println("logAfterThrowing() is running!");
System.out.println(joinPoint.getSignature().getName());
System.out.println("Exception : " + error);
System.out.println("******");
}
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("logAround() is running!");
System.out.println("method : " + joinPoint.getSignature().getName());
System.out.println("arguments : " + Arrays.toString(joinPoint.getArgs()));
System.out.println("Around before is running!");
joinPoint.proceed();
System.out.println("Around after is running!");
System.out.println("******");
}
}
<beans>
<aop:aspectj-autoproxy />
<bean id="studentOb" class="StudentImpl" />
<!-- Aspect -->
<bean id="logAspect" class="LoggingAspect" />
<aop:config>
<aop:aspect id="aspectLoggging" ref="logAspect">
<!-- @Before -->
<aop:pointcut id="pointCutBefore" expression="execution(* addStudent(..))" />
<aop:before method="logBefore" pointcut-ref="pointCutBefore" />
<!-- @After -->
<aop:pointcut id="pointCutAfter" expression="execution(* addStudent(..))" />
<aop:after method="logAfter" pointcut-ref="pointCutAfter" />
<!-- @AfterReturning -->
<aop:pointcut id="pointCutAfterReturning" expression="execution(* studentReturnValue(..))" />
<aop:after-returning method="logAfterReturning"
returning="result" pointcut-ref="pointCutAfterReturning" />
<!-- @AfterThrowing -->
<aop:pointcut id="pointCutAfterThrowing"
expression="execution(* studentThrowException(..))" />
<aop:after-throwing method="logAfterThrowing"
throwing="error" pointcut-ref="pointCutAfterThrowing" />
<!-- @Around -->
<aop:pointcut id="pointCutAround" expression="execution(* studentAround(..))" />
<aop:around method="logAround" pointcut-ref="pointCutAround" />
</aop:aspect>
</aop:config>
</beans>
public class AspectJTestApp {
public static void main(String[] args) throws Exception {
Resource res = new ClassPathResource("SpringConfig.xml");
BeanFactory factory = new XmlBeanFactory(res);
Student s = (Student) factory.getBean("studentOb");
s.addStudent();
s.studentReturnValue();
s.studentAround("SATYA");
s.studentThrowException();
}
}
-----------------output -------------------
Satya : new Student Added
Exception in thread "main" studentAround() is running, args : SATYA
studentThrowException() is running
java.lang.Exception: Student Error
at StudentImpl.studentThrowException(StudentImpl.java:17)
at AspectJTestApp.main(AspectJTestApp.java:20)