Spring Framework-An Introduction-Part III – Aspect Oriented Programming

My previous two posts on Spring Framework covered dependency injection, bean reuse and object lifecycle, autowiring and internationalization. This post will cover Aspect Oriented Programming(AOP).

All IT applications are developed with the end goal of addressing concern(s) or business requirement(s). Object oriented programming paradigm assists modularization of concerns. Modularization facilitates reuse and improves code maintenability. However there are certain concerns like security, transactions, logging, auditing etc which pervade the entire system and are essentially cross cutting. Implementing these concerns in the conventional fashion i.e. modular coding will be lead to code scattering all over the application. We need a completely different programming paradigm to address this issue. Aspect Oriented Programming (AOP) is the very paradigm for implementing such cross cutting concerns.

Before we begin on AOP and the breadth of support Spring framework provides to AOP, let us first familiarize ourselves with some terms commonly associated with AOP.

Advice: Advice is the additional code which is applied to existing code base. For example, in case we are interested in logging the processing time for every method execution, we need to add code at the start and completion of method execution, this additional code is advice.

Join point: Join point represents a particular point during the program execution. Examples of join points are method call, method execution, object instantiation, constructor execution, field references, exception handler etc. Note Spring AOP only supports method execution, for other join points use AspectJ.

Pointcut: Pointcut is the point of execution when the advice needs to be applied to a join point because the join point satisfies a certain condition for e.g. method name adheres to getter method format etc. For example consider we have a class with methods named getName, getPhoneNumber and calculate. Here all the three method executions represent join points; on the other hand we can define a pointcut for method calculate and apply advice for the same.

Aspect: The combination of advice and pointcut is an aspect.

Introduction: Introduction is addition of new methods or fields.

Target Object: Object which is adviced by one or more aspects. It is also called advised object.

AOP Proxy: A proxy created by AOP framework to implement advised contracts. In Spring AOP proxy is implemented using either JDK dynamic proxy or CGLIB proxy. If the target object implements an interface(s) that exposes the required methods, Spring will use the JDK’s java.lang.reflect.Proxy class. This class allows Spring to dynamically generate a new class that implements the necessary interfaces, weave in any advice, and proxy any calls to these interfaces to the target class. If the target class does not implement an interface, Spring uses the CGLIB library to generate a subclass for the target class. When creating this subclass, Spring weaves in advice and delegates calls to the subclass to the target class.

Weaving: Incorporation of aspects in the code base is called weaving. Weaving can be done either at compile time, class load time or runtime. Spring AOP does weaving at runtime.

Spring AOP classifies advice into the following categories:

Before advice: Advice that executes before a join point, but which does not have the ability to prevent execution flow proceeding to the join point (unless it throws an exception).

After returning advice: Advice to be executed after a join point completes normally: for example, if a method returns without throwing an exception.

After throwing advice: Advice to be executed if a method exits by throwing an exception.

After (finally) advice: Advice to be executed regardless of the means by which a join point exits (normal or exceptional return).

Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

Enough of theory let’s start coding. Spring Framework supports AOP using its own Spring AOP framework or the versatile AspectJ framework. The following tutorial intends use both options in turn highlighting the similarities and differences between the two.

First let’s look at AspectJ. To demonstrate the AOP capabilities I create simple Java class SampleObject with suitable attributes and methods. Here’s the source code of SampleObject class.

package com.spring.aop.aspectj;

public class SampleObject {

	public SampleObject() {

	}

	public static void test(){

	}

	public String run() {
		return "First Run";
	}

	public String run(String input){
		return input;
	}

	public void exceptionHandling(){
		throw new RuntimeException("Exception Handling");
	}

	public void exceptionHandling(Object o){
		throw new RuntimeException("Exception Handling Object");
	}

	public void handle(String input){
	}

	public void handle(Integer input){
	}

	public void handle(Object input){
	}

	public void doProcess(Object input) {

	}
}

To enhance SampleObject with AOP capabilities we define an additional Java class AOPObject. In this class we define pointcuts and advices; definition of pointcuts is done using annotations. Refer the following source code for AOPObject. An additional utility class AOPUtils’s source code is provided below.

package com.spring.aop.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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.aspectj.lang.annotation.Pointcut;

import com.spring.aop.util.AOPUtils;

@Aspect
public class AOPObject {

	public AOPObject() {
		
	}

	public AOPObject(String input) {
		
	}

	@Pointcut("execution(* *.run(..))")
	public String marker() {
		return "";
	}
	
	@Pointcut("execution(* *.run(String))")
	public void markerNew() {
		
	}

	@Pointcut("execution(* *.exceptionHandling())")
	public void markerForException() {
		
	}
	
	@Before("marker(),markerNew()")
	public void log(JoinPoint joinPoint) {
		System.out.println("+++++++++++++++++++++++++++++++++++++++");
		System.out.println("Before invoking the method: " + joinPoint.toShortString());
		Object[] args = joinPoint.getArgs();
		if (args != null && args.length > 0) {
			System.out.println("Name: " + args[0]);
		}
		Signature signature = joinPoint.getSignature();
		System.out.println("Information: " + signature.toLongString());
		System.out.println("+++++++++++++++++++++++++++++++++++++++");
	}
	
	@AfterReturning(value="marker(), markerNew()",
		returning="val")
	public void logReturn(String val) {
		System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
		System.out.println("After returning from the run method.");
		System.out.println("Ret Val: " + val);
		System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
		
	}

	@AfterThrowing(value="markerForException()",
			throwing="t")
	public void logThrow(Throwable t) {
		System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
		System.out.println("Processing exceptional condition during run method execution.");
		System.out.println("Exception thrown is: " + t);
		System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
	}
	
	@After("marker(), markerNew()")
	public void logFinally(JoinPoint joinPoint) {
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		AOPUtils.displayJoinPointDetails("Logging finally irrespective of method execution.", joinPoint);
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
	}
	
	@Around("markerNew()")
	public void logAround(ProceedingJoinPoint joinPoint) {
		System.out.println("#####Before method invokation.#####: " + joinPoint.toShortString());
		try {
			joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("#####After method invokation.#####: " + joinPoint.toShortString());
	}
	
	@Before("within(com.spring.aop.aspectj.Test)")
	public void withinMarker(JoinPoint joinPoint) {
		System.out.println("?????????????????????");
		System.out.println("Within Pointcut designator for Test class.");
		AOPUtils.displayJoinPointDetails("*.Test", joinPoint);
		System.out.println("?????????????????????");
	}
	
	@Before("this(com.spring.aop.aspectj.Test) && execution(* doProcess(..))")
	void thisMarker() {
		System.out.println("@@@@@@@@@@@@@@@@@@@");
		System.out.println("doProcess method of Test class is invoked.");
		System.out.println("@@@@@@@@@@@@@@@@@@@");
	}
	
	@Before("args(java.lang.String))")
	void argsMarker(JoinPoint joinPoint) {
		System.out.println("[][][][][][][][][][][][][]");
		AOPUtils.displayJoinPointDetails("Following Method with String argument invoked",
				joinPoint);
		System.out.println("[][][][][][][][][][][][][]");
	}
	
	@Before("this(com.spring.aop.aspectj.CollectionContainer))")
	void thisContainerMarker() {
		System.out.println("|||||||||||||||||||||||||||||||||");
		System.out.println("'this' pointcut is invoked.");
		System.out.println("|||||||||||||||||||||||||||||||||");
	}
	
	@Before("target(com.spring.aop.aspectj.CollectionContainer))")
	void targetContainerMarker() {
		System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
		System.out.println("'target' pointcut is invoked.");
		System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
	}

}
package com.spring.aop.util;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;

public class AOPUtils {
	
	public static void displayJoinPointDetails(String appendMessage, JoinPoint joinPoint) {
		Signature sign = joinPoint.getSignature();
		System.out.println(appendMessage + " : " + sign.toLongString());
	}

}

The first thing to notice is at line number 16 of AOPObject. To specify that this class provides AOP capabilities, the class has been annotated with @Aspect annotation. Let us know move on to the pointcut declarations. Refer line numbers 27, 32 and 37.


	@Pointcut("execution(* *.run(..))")
	public String marker() {
		return "";
	}

	@Pointcut("execution(* *.run(String))")
	public void markerNew() {
		
	}

	@Pointcut("execution(* *.exceptionHandling())")
	public void markerForException() {
		
	}

We have declared three methods namely marker, markerNew and markerForException.

Each method is annotated with a specific pointcut expression. That expression defines a constraint or limits the join points on which the advice will be applied.

For example consider the first expression ‘execution(* *.run(..))’. The expression states that this pointcut
applies on the execution of all classes whose methods are named run and the point cut applies irrespective of the return type and the number of method arguments. The * immediately following the execution open bracket denotes return type, the subsequent * denotes all classes. The .. within the brackets denotes method with any argument(s).

In the second example, we are specifically mentioning that the pointcut selects all classes whose method name is run and accept String as an argument. The third example we are interested in all classes whose method name is exceptionHandling and accepts no arguments.

The method implementation defined below the pointcut has no significance beyond being a placeholder for the AOP implementation. These methods can have return type and can use the default/friendly access modifier without compromising on the AOP functionality.Now that we have identified the point cut let’s look at how we can apply advice on that point cut. For that look at the following implementation within the AOPObject source code, refer the code between the line number 42 and line number 89.

	@Before("marker(),markerNew()")
	public void log(JoinPoint joinPoint) {
		System.out.println("+++++++++++++++++++++++++++++++++++++++");
		System.out.println("Before invoking the method: " + joinPoint.toShortString());
		Object[] args = joinPoint.getArgs();
		if (args != null && args.length > 0) {
			System.out.println("Name: " + args[0]);
		}
		Signature signature = joinPoint.getSignature();
		System.out.println("Information: " + signature.toLongString());
		System.out.println("+++++++++++++++++++++++++++++++++++++++");
	}
	
	@AfterReturning(value="marker(), markerNew()",
		returning="val")
	public void logReturn(String val) {
		System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
		System.out.println("After returning from the run method.");
		System.out.println("Ret Val: " + val);
		System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
		
	}

	@AfterThrowing(value="markerForException()",
			throwing="t")
	public void logThrow(Throwable t) {
		System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
		System.out.println("Processing exceptional condition during run method execution.");
		System.out.println("Exception thrown is: " + t);
		System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
	}
	
	@After("marker(), markerNew()")
	public void logFinally(JoinPoint joinPoint) {
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		AOPUtils.displayJoinPointDetails("Logging finally irrespective of method execution.", joinPoint);
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
	}
	
	@Around("markerNew()")
	public void logAround(ProceedingJoinPoint joinPoint) {
		System.out.println("#####Before method invokation.#####: " + joinPoint.toShortString());
		try {
			joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("#####After method invokation.#####: " + joinPoint.toShortString());
	}

We have earlier discussed the different advice types, we will apply them here to create the aspect. So let’s look at the first method log. The point cuts declared using the marker and markerNew method are combined with the before advice type in the log method. Refer the log method annotation.

@Before("marker(),markerNew()")

What this does is that before invocation of the methods defined by marker and markerNew point cuts, the
implementation of log method will execute. The log method can have no arguments or can have a single argument JoinPoint. Using the JoinPoint argument provides the developer with the ability to gathering metadata details around the method on whom the AOP is applied. In my current implementation I have highlighted some areas of information available like method arguments, method signature etc.

A method execution can return a void or a return value. In case developers are interested in intercepting the method invocation post execution, they can use the AfterReturning advice type. Refer the following code:

   	@AfterReturning(value="marker(), markerNew()",
		returning="val")
	public void logReturn(String val) {
		System.out.println("After returning from the run method.");
		System.out.println("Ret Val: " + val);
		
	}

In the annotation we use the value attribute to reference the pointcut and the returning attribute to provide a name for the return value. The method implementation uses the same return value name ‘val’ along with the appropriate class type.

In rare occasions the method implementation throw exceptions. In case developers need to intercept these
exceptions, they can use the AfterThrowing advice type. Refer line number of the AOPObject source. Ready handle to the thrown exception is provided via the throwing attribute.

 
	@AfterThrowing(value="markerForException()",
			throwing="t")
	public void logThrow(Throwable t) {
		System.out.println("Processing exceptional condition during run method execution.");
		System.out.println("Exception thrown is: " + t);
	}

Use the After advice type to do some advice processing during the finally block code run. Here’s the implementation.

	@After("marker(), markerNew()")
	public void logFinally() {
		System.out.println("Logging finally irrespective of method execution.");
	}
 

Lastly developers might be interested in getting information or implementing some aspect encompassing the method execution i.e. before and after, they can use the Around advice type. Refer the sample implementation in AOPObject line number 82.

	@Around("markerNew()")
	public void logAround(ProceedingJoinPoint joinPoint) {
		System.out.println("Before method invokation.");
		try {
			joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("After method invokation.");
	}

The source code joinPoint.proceed in line number in the source code above controls the execution of method. The developer is free to write custom program before and after this code. Unlike using the JoinPoint class we are using ProceedingJoinPoint class which provides access to the proceed method.

To understand all that has been explained so far let’s create a test class AOPTest1. The source code of the class is as below:

package com.spring.test;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.aop.aspectj.SampleObject;

public class AOPTest1 {

	public static void main(String[] args) {
				
		ConfigurableApplicationContext ctx 
			= new ClassPathXmlApplicationContext (new String[] {"aop1.xml"});

		SampleObject obj = (SampleObject)ctx.getBean("obj");
		System.out.println("{}{}{}{}{}{}{}{}{}{}{}{}{}{}");
		obj.run();
		System.out.println("{}{}{}{}{}{}{}{}{}{}{}{}{}{}");
		obj.run("Testing....");
		System.out.println("{}{}{}{}{}{}{}{}{}{}{}{}{}{}");
		obj.exceptionHandling();
		System.out.println("{}{}{}{}{}{}{}{}{}{}{}{}{}{}");
	}
}

Here’s the Spring configuration 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<bean id="obj" class="com.spring.aop.aspectj.SampleObject" />
	<bean id="aopObj" class="com.spring.aop.aspectj.AOPObject" />
	
	<aop:aspectj-autoproxy />		
</beans>

Running the test class generates the following output:

{}{}{}{}{}{}{}{}{}{}{}{}{}{}
+++++++++++++++++++++++++++++++++++++++
Before invoking the method: execution(SampleObject.run())
Information: public java.lang.String com.spring.aop.aspectj.SampleObject.run()
+++++++++++++++++++++++++++++++++++++++
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
After returning from the run method.
Ret Val: First Run
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Logging finally irrespective of method execution. : public java.lang.String 

com.spring.aop.aspectj.SampleObject.run()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{}{}{}{}{}{}{}{}{}{}{}{}{}{}
#####Before method invokation.#####: execution(SampleObject.run(..))
[][][][][][][][][][][][][]
Following Method with String argument invoked : public java.lang.String com.spring.aop.aspectj.SampleObject.run
(java.lang.String)
[][][][][][][][][][][][][]
+++++++++++++++++++++++++++++++++++++++
Before invoking the method: execution(SampleObject.run(..))
Name: Testing....
Information: public java.lang.String com.spring.aop.aspectj.SampleObject.run(java.lang.String)
+++++++++++++++++++++++++++++++++++++++
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
After returning from the run method.
Ret Val: Testing....
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Logging finally irrespective of method execution. : public java.lang.String 
com.spring.aop.aspectj.SampleObject.run(java.lang.String)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#####After method invokation.#####: execution(SampleObject.run(..))
{}{}{}{}{}{}{}{}{}{}{}{}{}{}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Processing exceptional condition during run method execution.
Exception thrown is: java.lang.RuntimeException: Exception Handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Exception in thread "main" java.lang.RuntimeException: Exception Handling
	at com.spring.aop.aspectj.SampleObject.exceptionHandling(SampleObject.java:22)
	at com.spring.aop.aspectj.SampleObject$$FastClassByCGLIB$$6d2e8fc5.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
	at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint
(Cglib2AopProxy.java:688)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:150)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke
(ExposeInvocationInterceptor.java:89)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept
(Cglib2AopProxy.java:621)
	at com.spring.aop.aspectj.SampleObject$$EnhancerByCGLIB$$e056b02c.exceptionHandling(<generated>)
	at com.spring.test.AOPTest1.main(AOPTest1.java:21)

Only the relevant logging statements have been retained. Let’s break the output into individual runs.

First let’s look at the output for the following section of the test code:

		obj.run();

The output generated was

+++++++++++++++++++++++++++++++++++++++
Before invoking the method: execution(SampleObject.run())
Information: public java.lang.String com.spring.aop.aspectj.SampleObject.run()
+++++++++++++++++++++++++++++++++++++++
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
After returning from the run method.
Ret Val: First Run
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Logging finally irrespective of method execution. : public java.lang.String 
com.spring.aop.aspectj.SampleObject.run()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

The first method to get invoked was the advice associated with the marker point cut. The next advice to get
executed is AfterReturning. And the last advice to get executed is the After advice.
Now let’s look at the second portion of the test code:

obj.run("Testing....");

The output generated for this code was:

#####Before method invokation.#####: execution(SampleObject.run(..))
[][][][][][][][][][][][][]
Following Method with String argument invoked : public java.lang.String com.spring.aop.aspectj.SampleObject.run
(java.lang.String)
[][][][][][][][][][][][][]
+++++++++++++++++++++++++++++++++++++++
Before invoking the method: execution(SampleObject.run(..))
Name: Testing....
Information: public java.lang.String com.spring.aop.aspectj.SampleObject.run(java.lang.String)
+++++++++++++++++++++++++++++++++++++++
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
After returning from the run method.
Ret Val: Testing....
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Logging finally irrespective of method execution. : public java.lang.String 
com.spring.aop.aspectj.SampleObject.run(java.lang.String)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#####After method invokation.#####: execution(SampleObject.run(..))

The first advice to be processed is Around advice. The logging statement within the logAround method is printed.

After invocation of the proceed method on the JoinPoint, the next advice to be processed is the args pointcut designator. We will cover this later on in the post. The next advice to be processed is the Before advice associated with the log method. On completion of the method execution the AfterReturning advice is triggered and the last advice to run is After advice.

Now let’s look at the output generated by running the following code:

	obj.exceptionHandling();

The output generated is follows:

{}{}{}{}{}{}{}{}{}{}{}{}{}{}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Processing exceptional condition during run method execution.
Exception thrown is: java.lang.RuntimeException: Exception Handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Exception in thread "main" java.lang.RuntimeException: Exception Handling
	at com.spring.aop.aspectj.SampleObject.exceptionHandling(SampleObject.java:22)
	at com.spring.aop.aspectj.SampleObject$$FastClassByCGLIB$$6d2e8fc5.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
	at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint
(Cglib2AopProxy.java:688)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:150)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke
(ExposeInvocationInterceptor.java:89)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept
(Cglib2AopProxy.java:621)
	at com.spring.aop.aspectj.SampleObject$$EnhancerByCGLIB$$3ef22468.exceptionHandling(<generated>)
	at com.spring.test.AOPTest1.main(AOPTest1.java:21)

The AfterThrowing advice is invoked and no further processing is taking place due to the RuntimeException.
The examples used so far maintained a clear demarcation between the pointcut declaration and advice. However the framework does provide an alternative to combining the two together. Refer the following piece of code in the AOPObject class at line number 92.

	@Before("within(com.spring.aop.aspectj.Test)")
	public void withinMarker(JoinPoint joinPoint) {
		System.out.println("Within Pointcut designator for Test class.");
		AOPUtils.displayJoinPointDetails("*.Test", joinPoint);
	}

Here we are applying the before advice type and using the point cut designator within to state that any method executions within the Test class will be intercepted. The pointcut ‘within(com.spring.aop.aspectj.Test)’ is integrated with the advice annotation. For your ready reference I am enclosing the source code of AOPTest2.

package com.spring.test;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.aop.aspectj.Test;

public class AOPTest2 {

	public static void main(String[] args) {
				
		ConfigurableApplicationContext ctx 
			= new ClassPathXmlApplicationContext (new String[] {"aop2.xml"});
		Test test = (Test)ctx.getBean("testObj");
		System.out.println("=====================================");
		test.invoke();
		System.out.println("=====================================");
		test.doProcess("");
		System.out.println("=====================================");
		
	}
}

aop2.xml source

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<bean id="aopObj" class="com.spring.aop.aspectj.AOPObject" />
	<bean id="testObj" class="com.spring.aop.aspectj.Test" />

	<aop:aspectj-autoproxy />		
</beans>

Let’s look at the other pointcut designators like this, target and args. Refer the source code within the line
numbers 100 and 127.

	@Before("this(com.spring.aop.aspectj.Test) && execution(* doProcess(..))")
	void thisMarker() {
		System.out.println("doProcess method of Test class is invoked.");
	}
	
	@Before("args(java.lang.String))")
	void argsMarker(JoinPoint joinPoint) {
		AOPUtils.displayJoinPointDetails("Following Method with String argument invoked",
				joinPoint);
	}

The ‘this’ designator is used in the context of the bean. If the bean type/class matches the name specified in the this expression, the pointcut condition is considered satisfied. Note that this checks the compile time type of the bean and not the runtime type. To validate with reference to runtime type you will need to use the ‘target’ designator.

The test class AOPTest2 run is displayed below:

=====================================
?????????????????????
Within Pointcut designator for Test class.
*.Test : public void com.spring.aop.aspectj.Test.invoke()
?????????????????????
=====================================
?????????????????????
Within Pointcut designator for Test class.
*.Test : public void com.spring.aop.aspectj.Test.doProcess(java.lang.String)
?????????????????????
@@@@@@@@@@@@@@@@@@@
doProcess method of Test class is invoked.
@@@@@@@@@@@@@@@@@@@
[][][][][][][][][][][][][]
Following Method with String argument invoked : public void com.spring.aop.aspectj.Test.doProcess(java.lang.String)
[][][][][][][][][][][][][]
=====================================

The output clearly shows that the invocation of invoke method causes the withinMarker method’s before advice to be triggered. Invocation of doProcess method triggers the withinMarker method’s advice is triggered for Test class and the thisMarker method associated with advice associated with Test class and execution of doProcess method is triggered.

Now let’s look at the following piece of code within AOPObject.

	@Before("args(java.lang.String))")
	void argsMarker(JoinPoint joinPoint) {
		System.out.println("[][][][][][][][][][][][][]");
		AOPUtils.displayJoinPointDetails("Following Method with String argument invoked",
				joinPoint);
		System.out.println("[][][][][][][][][][][][][]");
	}

The args pointcut designator checks the method arguments of all invoked methods which match to the specified method signature. The invocation of doProcess method of Test class triggers the advice associated with argsMarker method.

There is another pointcut designator called target which also accepts a class as its processing parameter. Let’s try and understand the difference between this and target pointcut designator. The basic difference between the two is that this designator evaluates the compile time class reference while target evaluates the runtime class reference. To understand this let’s use an example. Create a class Container and CollectionContainer. The source code of the two classes is shown below:

package com.spring.aop.aspectj;

public class Container {

	public void add(Object o){
		
	}
	
	public void remove(Object o){
		
	}		
}
package com.spring.aop.aspectj;


public class CollectionContainer extends Container {

}

The CollectionContainer bean is defined in the aop3.xml configuration file. Here’s the xml details.

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<bean id="obj" class="com.spring.aop.aspectj.SampleObject" />
	<bean id="aopObj" class="com.spring.aop.aspectj.AOPObject" />
	<bean id="container" class="com.spring.aop.aspectj.CollectionContainer" />
	
	<aop:aspectj-autoproxy />		
</beans>

Here’s the test code AOP3Test:

package com.spring.test;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.aop.aspectj.Container;
import com.spring.aop.aspectj.SampleObject;

public class AOPTest3 {

	public static void main(String[] args) {
				
		ConfigurableApplicationContext ctx 
			= new ClassPathXmlApplicationContext (new String[] {"aop3.xml"});
		
		System.out.println("============================ Container");
		Container container = (Container)ctx.getBean("container");
		container.add(null);

		SampleObject obj = (SampleObject)ctx.getBean("obj");
		
		System.out.println("============================ handle(String)");
		obj.handle("");

		System.out.println("============================ handle(Object)");
		obj.handle(new Object());

		System.out.println("============================ doProcess(Object)");
		obj.doProcess(new Object());

		System.out.println("=============================== doProcess(String)");
		obj.doProcess("");
		
		System.out.println("============================ handle(Integer)");
		obj.handle(Integer.valueOf(1));
		
	}
}

We have created two new methods within the AOPObject class for Container related classes. The two methods are thisContainerMarker and targetContainerMarker. This first one uses ‘this’ designator for CollectionContainer and second one uses ‘target’ for CollectionContainer.

On running the test class let’s look at what the output the following piece of code generates:

		Container container = (Container)ctx.getBean("container");
		container.add(null);

The ouput is

============================ Container
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
'target' pointcut is invoked.
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Clearly only the target pointcut is invoked, this is because the class reference used in the test code is Container and the runtime reference is CollectionContainer. The subsequent test code in AOP3Test tests whether the args designator uses runtime or static reference for processing. The output generated is as follows:

============================ handle(String)
[][][][][][][][][][][][][]
Following Method with String argument invoked : public void com.spring.aop.aspectj.SampleObject.handle
(java.lang.String)
[][][][][][][][][][][][][]
============================ handle(Object)
============================ doProcess(Object)
=============================== doProcess(String)
[][][][][][][][][][][][][]
Following Method with String argument invoked : public void com.spring.aop.aspectj.SampleObject.doProcess
(java.lang.Object)
[][][][][][][][][][][][][]
============================ handle(Integer)

Clearly args designator works on the runtime parameter. It processes the method handle(java.lang.String) as a match as long as the runtime method argument is String. The same applies for doProcess even thought the method signature accepts Object. If the runtime argument is String it treats the method as a match.

Upto now we have looked at AspectJ capabilities available via the Spring Framework. AspectJ as a standalone AOP framework has far greater capabilities, however Spring has limited itself to implementing the most commonly used ones. We now move on to looking at what Spring AOP has to offer on its own.

Spring AOP provides a more simplified methodology of defining advice and pointcuts.Spring AOP provides an interface for each advice type. Here are the Spring AOP interfaces: MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice, AfterAdvice and MethodInterceptor. Except for MethodInterceptor the rest of the interfaces names match the advice type. The MethodInterceptor replicates the Around advice. To gain a better understanding let’s implement a Java class AOPDiffObject. Here’s the source code for AOPDiffObject.

package com.spring.aop.spring;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;

public class AOPDiffObject implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice,
		MethodInterceptor {

	public AOPDiffObject() {
		
	}

	//Implementation of MethodBeforeAdvice interface
	@Override
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		System.out.println("########## Before Advice Start ###########");
		System.out.println("Diff:Before invoking the run method.");
		if (args != null && args.length > 0) {
			System.out.println("Diff:Argument Value: " + args[0]);
		} else {
			System.out.println("Diff:Argument : None.");
		}
		System.out.println("########## Before Advice End ###########");
	}

	//Implementation of AfterReturningAdvice interface
	@Override
	public void afterReturning(Object returnVal, Method method, Object[] args,
			Object target) throws Throwable {
		System.out.println("########## After Returning Advice Start ###########");
		System.out.println("Diff:After returning from the run method.");
		System.out.println("Diff:Ret Val: " + returnVal);		
		System.out.println("########## After Returning Advice End ###########");
	}

	//ThrowsAdvice interface does define any methods but implementations are expected to implement
	//afterThrowing method as shown below
	public void afterThrowing(Throwable throwable) throws Throwable {
		System.out.println("########## After Throwing Advice Start ###########");
		System.out.println("Diff:Exception thrown.");
		System.out.println(throwable);
		System.out.println("########## After Throwing Advice End ###########");
	}

	//Implementation of MethodInterceptor interface
	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("########## Around Advice Start ###########");
		System.out.println("Diff:Before method invokation.");
		Object retValue = null;
		try {
			retValue = invocation.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("Diff:After method invokation.");
		System.out.println("########## Around Advice End ###########");
		return retValue;
	}	
}

The before method realization implements the before Advice, similarly afterReturning method realization implements the After returning advice, afterThrowing method realization implements the After throwing advice and invoke method realization implements the Around advice. I was not able to find an implementation for After finally advice in Spring AOP.

Here’s the Spring configuration 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<bean id="obj" class="com.spring.aop.aspectj.SampleObject" />
	
	<bean id="aopObject" class="com.spring.aop.spring.AOPDiffObject" />
	<bean id="advisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
		<property name="advice" ref="aopObject" />
		<property name="expression" value="execution(* *.run(..))" />
	</bean>
	<bean id="advisorTwo" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
		<property name="advice" ref="aopObject" />
		<property name="expression" value="execution(* *.run(String))" />
	</bean>
	
	<aop:aspectj-autoproxy />		
</beans>

In the configuration xml refer the lines 16 and 20. Here we are defining the association between pointcuts and advices. These are used for implementing aspects in the implementation code. Spring AOP provides three methods for defining pointcut expressions. Perl regex, java regex and AspectJ. I am using AspectJ for its richness and also to maintain ease of mapping between understanding the AspectJ and Spring AOP implementation.

For academic reasons here’s the test class and output of the test run

package com.spring.test;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.aop.aspectj.Container;
import com.spring.aop.aspectj.SampleObject;
import com.spring.aop.aspectj.Test;

public class AOPTest4 {

	public static void main(String[] args) {
				
		ConfigurableApplicationContext ctx 
			= new ClassPathXmlApplicationContext (new String[] {"aop4.xml"});
		SampleObject obj = (SampleObject)ctx.getBean("obj");
		obj.run();
		System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
		obj.run("Testing....");
		
	}
}
19 Apr, 2011 1:53:37 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@32fb4f: startup date [Tue Apr 19 13:53:37 IST 2011]; root of context hierarchy
19 Apr, 2011 1:53:37 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [aop4.xml]
19 Apr, 2011 1:53:37 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@544ec1: 
defining beans [obj,aopObject,advisor,advisorTwo,org.springframework.aop.config.internalAutoProxyCreator]; root of factory hierarchy
########## Around Advice Start ###########
Diff:Before method invokation.
########## Before Advice Start ###########
Diff:Before invoking the run method.
Diff:Argument : None.
########## Before Advice End ###########
########## After Returning Advice Start ###########
Diff:After returning from the run method.
Diff:Ret Val: First Run
########## After Returning Advice End ###########
Diff:After method invokation.
########## Around Advice End ###########
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
########## Around Advice Start ###########
Diff:Before method invokation.
########## Before Advice Start ###########
Diff:Before invoking the run method.
Diff:Argument Value: Testing....
########## Before Advice End ###########
########## Around Advice Start ###########
Diff:Before method invokation.
########## Before Advice Start ###########
Diff:Before invoking the run method.
Diff:Argument Value: Testing....
########## Before Advice End ###########
########## After Returning Advice Start ###########
Diff:After returning from the run method.
Diff:Ret Val: Testing....
########## After Returning Advice End ###########
Diff:After method invokation.
########## Around Advice End ###########
########## After Returning Advice Start ###########
Diff:After returning from the run method.
Diff:Ret Val: Testing....
########## After Returning Advice End ###########
Diff:After method invokation.
########## Around Advice End ###########

That’s all from my end at the moment.

About these ads
Categories: spring, spring framework | Tags: | 4 Comments

Post navigation

4 thoughts on “Spring Framework-An Introduction-Part III – Aspect Oriented Programming

  1. Kunal

    This is a great blog, I was interested in reading more about AOP/Object lifecycles in Spring. Thanks for the articles.

  2. Pingback: RESTEasy Client Framework (RESTful Web Services Client) – A Tutorial | My experiments with technology

  3. Ganesh Dudhade

    when i run AOPTest1.java i found following error:
    Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘obj’ defined in class path resource [aop1.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: warning no match for this type name: com.spring.aop.aspectj.CollectionContainer [Xlint:invalidAbsoluteTypeName]

  4. Gocha

    Hi your example works fine and this is an great article. I tried to use this to log call of methods in my RMI service but i can’t see any output (either client or server side…) Could you help me?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com. The Adventure Journal Theme.

Follow

Get every new post delivered to your Inbox.

Join 60 other followers

%d bloggers like this: