Spring AOP with AspectJ Annotation Configuration Example
As we have already seen the AOP advise methods and its implementation through XML.
Let’s discuss AOP advises with annotation
In order to achieve this, we need to follow below steps
Annotate our aspect class with @Aspect annotation.
We need to define the aspect as a bean in spring xml file
We need to define the advise methods using annotation like @Before,@After etc
Project structure looks like below
Create a pom.xml as below
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>Spring</groupId>
- <artifactId>SpringAOP</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>SpringAOP</name>
- <url>http://maven.apache.org</url>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>4.2.4.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>4.2.4.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.7.3</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Spring</groupId> <artifactId>SpringAOP</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>SpringAOP</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.7.3</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
Lets first create a SimpleCalculator class as below
- package com.kb;
- public class SimpleCalculator {
- public int add(int x,int y){
- System.out.println("inside Add");
- return x+y;
- }
- public int subtract(int x,int y){
- System.out.println("inside subtract");
- return x-y;
- }
- }
package com.kb; public class SimpleCalculator { public int add(int x,int y){ System.out.println("inside Add"); return x+y; } public int subtract(int x,int y){ System.out.println("inside subtract"); return x-y; } }
Now Lets write our Aspect classes using annotations as below
First lets write Before aspect class as below
- package com.kb;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- @Aspect
- public class MyBeforeAspect {
- @Pointcut("execution(* com.kb.SimpleCalculator.*(..))")
- public void pointcutName(){}
- @Before("pointcutName()")//applying pointcut on before advice
- public void myadvice(JoinPoint jp)
- {
- System.out.println("my before advice");
- }
- }
package com.kb; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyBeforeAspect { @Pointcut("execution(* com.kb.SimpleCalculator.*(..))") public void pointcutName(){} @Before("pointcutName()")//applying pointcut on before advice public void myadvice(JoinPoint jp) { System.out.println("my before advice"); } }
As you can see that , class is annotated with @Aspect to define this class as an Aspect.
We have defined pointcut expression using @Pointcut annotation by passing pointcut expression.
We have written empty method just to use it as a pointcut in the advice.
We have defined Before advise using @Before annotation by passing pointcut name which is “pointcutName” in our case.
Lets write After aspect class as below
- package com.kb;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- @Aspect
- public class MyAfterAspect {
- @Pointcut("execution(* com.kb.SimpleCalculator.*(..))")
- public void pointcutName(){}
- @After("pointcutName()")//applying pointcut on after advice
- public void myadvice(JoinPoint jp)
- {
- System.out.println("my after advice");
- }
- }
package com.kb; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyAfterAspect { @Pointcut("execution(* com.kb.SimpleCalculator.*(..))") public void pointcutName(){} @After("pointcutName()")//applying pointcut on after advice public void myadvice(JoinPoint jp) { System.out.println("my after advice"); } }
As you can see that , class is annotated with @Aspect to define this class as an Aspect.
We have defined pointcut expression using @Pointcut annotation by passing pointcut expression.
We have written empty method just to use it as a pointcut in the advice.
We have defined After advise using @After annotation by passing pointcut name which is “pointcutName” in our case.
Lets write AfterReturning aspect class as below
- package com.kb;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.AfterReturning;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- @Aspect
- public class MyAfterReturningAspect {
- @Pointcut("execution(* com.kb.SimpleCalculator.*(..))")
- public void pointcutName(){}
- @AfterReturning("pointcutName()")//applying pointcut on after returning //advice
- public void myadvice(JoinPoint jp)
- {
- System.out.println("my after returning advice");
- }
- }
package com.kb; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyAfterReturningAspect { @Pointcut("execution(* com.kb.SimpleCalculator.*(..))") public void pointcutName(){} @AfterReturning("pointcutName()")//applying pointcut on after returning //advice public void myadvice(JoinPoint jp) { System.out.println("my after returning advice"); } }
As you can see that , class is annotated with @Aspect to define this class as an Aspect.
We have defined pointcut expression using @Pointcut annotation by passing pointcut expression.
We have written empty method just to use it as a pointcut in the advice.
We have defined AfterReturning advise using @AfterReturning annotation by passing pointcut name which is “pointcutName” in our case.
Lets write AfterThrowing aspect class as below
- package com.kb;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.AfterThrowing;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- @Aspect
- public class MyAfterThrowingAspect {
- @Pointcut("execution(* com.kb.SimpleCalculatorThrowsException.*(..))")
- public void pointcutName(){}
- @AfterThrowing("pointcutName()")//applying pointcut on after throwing //advice
- public void myadvice(JoinPoint jp)
- {
- System.out.println("my after throwing advice");
- }
- }
package com.kb; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyAfterThrowingAspect { @Pointcut("execution(* com.kb.SimpleCalculatorThrowsException.*(..))") public void pointcutName(){} @AfterThrowing("pointcutName()")//applying pointcut on after throwing //advice public void myadvice(JoinPoint jp) { System.out.println("my after throwing advice"); } }
As you can see that , class is annotated with @Aspect to define this class as an Aspect.
We have defined pointcut expression using @Pointcut annotation by passing pointcut expression.
We have written empty method just to use it as a pointcut in the advice.
We have defined AfterThrowing advise using @AfterThrowing annotation by passing pointcut name which is “pointcutName” in our case.
Also define the class which actually throws an exception so that above advice will be called
- package com.kb;
- public class SimpleCalculatorThrowsException {
- public int add(int x,int y){
- System.out.println("inside Add");
- throw new RuntimeException();
- }
- }
package com.kb; public class SimpleCalculatorThrowsException { public int add(int x,int y){ System.out.println("inside Add"); throw new RuntimeException(); } }
Let’s write Around aspect class as below
- package com.kb;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- @Aspect
- public class MyAroundAspect {
- @Pointcut("execution(* com.kb.SimpleCalculator.*(..))")
- public void pointcutName(){}
- @Around("pointcutName()")//applying pointcut on before advice
- public Object myAdvice(ProceedingJoinPoint jp){
- System.out.println("Around -- Before the method "+jp.getSignature().getName()+" execution");
- Object[] args=null;
- Object value=null;
- try {
- args=jp.getArgs();
- if((Integer)args[0] == 10){
- value= jp.proceed();
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
- System.out.println("Around -- After the method "+jp.getSignature().getName()+" execution");
- return value;
- }
- }
package com.kb; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyAroundAspect { @Pointcut("execution(* com.kb.SimpleCalculator.*(..))") public void pointcutName(){} @Around("pointcutName()")//applying pointcut on before advice public Object myAdvice(ProceedingJoinPoint jp){ System.out.println("Around -- Before the method "+jp.getSignature().getName()+" execution"); Object[] args=null; Object value=null; try { args=jp.getArgs(); if((Integer)args[0] == 10){ value= jp.proceed(); } } catch (Throwable e) { e.printStackTrace(); } System.out.println("Around -- After the method "+jp.getSignature().getName()+" execution"); return value; } }
As you can see that , class is annotated with @Aspect to define this class as an Aspect.
We have defined pointcut expression using @Pointcut annotation by passing pointcut expression.
We have written empty method just to use it as a pointcut in the advice.
We have defined Around advise using @Around annotation by passing pointcut name which is “pointcutName” in our case
Now after defining all the Aspects using annotations, we need to make them as spring beans by defining them in spring configuration file.
Lets create spring configuration xml file
- <?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"
- xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd">
- <aop:aspectj-autoproxy />
- <bean id="simpleCalc" class="com.kb.SimpleCalculator"/>
- <bean id="simpleCalcException" class="com.kb.SimpleCalculatorThrowsException"/>
- <bean id="myBeforeAspect" class="com.kb.MyBeforeAspect" />
- <bean id="myAfterAspect" class="com.kb.MyAfterAspect" />
- <bean id="myAfterReturningAspect" class="com.kb.MyAfterReturningAspect" />
- <bean id="myAfterThrowingAspect" class="com.kb.MyAfterThrowingAspect" />
- <bean id="myAroundAspect" class="com.kb.MyAroundAspect" />
- </beans>
<?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" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <aop:aspectj-autoproxy /> <bean id="simpleCalc" class="com.kb.SimpleCalculator"/> <bean id="simpleCalcException" class="com.kb.SimpleCalculatorThrowsException"/> <bean id="myBeforeAspect" class="com.kb.MyBeforeAspect" /> <bean id="myAfterAspect" class="com.kb.MyAfterAspect" /> <bean id="myAfterReturningAspect" class="com.kb.MyAfterReturningAspect" /> <bean id="myAfterThrowingAspect" class="com.kb.MyAfterThrowingAspect" /> <bean id="myAroundAspect" class="com.kb.MyAroundAspect" /> </beans>
Now lets run the AOPTest class to see the output
- package com.kb;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class AOPTest {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
- SimpleCalculator calculator = (SimpleCalculator) context.getBean("simpleCalc");
- int res1= calculator.add(10, 5);
- System.out.println("addition result is "+res1);
- System.out.println("............");
- int res2= calculator.subtract(10, 5);
- System.out.println("subtracted result is "+res2);
- }
- }
package com.kb; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AOPTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); SimpleCalculator calculator = (SimpleCalculator) context.getBean("simpleCalc"); int res1= calculator.add(10, 5); System.out.println("addition result is "+res1); System.out.println("............"); int res2= calculator.subtract(10, 5); System.out.println("subtracted result is "+res2); } }
Observe the output
before each method got executed Before advice and Around advice got executed
after the method execution After,AfterReturning and Around advice got executed.
Now lets run the AOPTestException class to see the output
- package com.kb;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class AOPTestException {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
- SimpleCalculatorThrowsException calculator = (SimpleCalculatorThrowsException) context.getBean("simpleCalcException");
- int res1= calculator.add(10, 5);
- System.out.println("addition result is "+res1);
- }
- }
package com.kb; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AOPTestException { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); SimpleCalculatorThrowsException calculator = (SimpleCalculatorThrowsException) context.getBean("simpleCalcException"); int res1= calculator.add(10, 5); System.out.println("addition result is "+res1); } }
Observe the output below
Output shows that AfterThrowing advice got executed when the method throws an exception
Crisp & Clear explanation ..
– Chethu