Around Aspect XML implementation example
create a spring maven project so that we can manage our dependencies in the pom.xml easily.
Project structure looks like below
Define the pom.xml file as below to include AspectJ jars and spring jars
- <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>aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.5.4</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>aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
Let’s create a class which contains a business logic on which we apply Advice.
- package com.kb;
- public class SimpleCalculator {
- public int add(int x,int y){
- return x+y;
- }
- public int subtract(int x,int y){
- return x-y;
- }
- }
package com.kb; public class SimpleCalculator { public int add(int x,int y){ return x+y; } public int subtract(int x,int y){ return x-y; } }
This class has 2 methods where each method performs some business logic,which is addition and subtraction.
Now let’s write the Aspect class as below
- package com.kb;
- import org.aspectj.lang.ProceedingJoinPoint;
- public class MyAroundAspect {
- public Object myAdvice(ProceedingJoinPoint jp){
- System.out.println("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("After the method "+jp.getSignature().getName()+" execution");
- return value;
- }
- }
package com.kb; import org.aspectj.lang.ProceedingJoinPoint; public class MyAroundAspect { public Object myAdvice(ProceedingJoinPoint jp){ System.out.println("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("After the method "+jp.getSignature().getName()+" execution"); return value; } }
This Aspect has an advice called myAdvice whose action is to print the log with method name
It takes a parameter called ProceedingJoinPoint which helps to control the execution of the target method.
When we use jp.proceed() , the advised method continues the execution.
So we can use Around advice to execute some code before and after the execution of the advised method.
Based on some condition, we can also stop the further execution of the advised method.
We are continuing the advised method execution only if the first argument passed is 10,otherwise we will stop the execution.
Now let’s create a beans.xml file which is the spring configuration file where we define our aspect beans and configure the AOP as below
- <?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="myAroundAspect" class="com.kb.MyAroundAspect" />
- <aop:config>
- <aop:aspect id="myAspect" ref="myAroundAspect">
- <aop:pointcut id="pointCutAfter"
- expression="execution(* *.*(..))" />
- <aop:around method="myAdvice" pointcut-ref="pointCutAfter" />
- </aop:aspect>
- </aop:config>
- </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="myAroundAspect" class="com.kb.MyAroundAspect" /> <aop:config> <aop:aspect id="myAspect" ref="myAroundAspect"> <aop:pointcut id="pointCutAfter" expression="execution(* *.*(..))" /> <aop:around method="myAdvice" pointcut-ref="pointCutAfter" /> </aop:aspect> </aop:config> </beans>
Lets write a class which calls the actual business logic method as below
- 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);
- 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); int res2= calculator.subtract(10, 5); System.out.println("Subtracted result is "+res2); } }
Run the above class and see the output as below
Observe the output, before and after the execution of add and subtract method,our advice code has been executed.
Since we passed first argument as 10, we got our advised method execution successfully.
Lets modify the above Test program by passing 5 as the first value in the subtract method call as below
- 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);
- int res2= calculator.subtract(5,10);
- 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); int res2= calculator.subtract(5,10); System.out.println("subtracted result is "+res2); } }
See the output as below
Add method got executed successfully, but subtract method failed to execute.
Since subtract method call has passed 5 as the first argument, it did not get executed as our Around advice has a control to stop its execution if the first parameter is not 10.
So using Around advice, we can access the method arguments and we can control the advised method execution.