Aspect Oriented Programming and AOP in Spring Framework
Aspect oriented programming(AOP) as the name suggests uses aspects in programming. It can be defined as the breaking of code into different modules, also known as modularisation, where the aspect is the key unit of modularity. Aspects enable the implementation of crosscutting concerns such as- transaction, logging not central to business logic without cluttering the code core to its functionality. It does so by adding additional behaviour that is the advice to the existing code. For example- Security is a crosscutting concern, in many methods in an application security rules can be applied, therefore repeating the code at every method, define the functionality in a common class and control were to apply that functionality in the whole application.
Dominant Frameworks in AOP:
AOP includes programming methods and frameworks on which modularisation of code is supported and implemented. Let’s have a look at the three dominant frameworks in AOP:
- AspectJ: It is an extension for Java programming created at PARC research centre. It uses Java like syntax and included IDE integrations for displaying crosscutting structure. It has its own compiler and weaver, on using it enables the use of full AspectJ language.
- JBoss: It is an open source Java application server developed by JBoss, used for Java development.
- Spring: It uses XML based configuration for implementing AOP, also it uses annotations which are interpreted by using a library supplied by AspectJ for parsing and matching.
Currently, AspectJ libraries with Spring framework are dominant in the market, therefore let’s have an understanding of how Aspect-oriented programming works with Spring.
How Aspect-Oriented Programming works with Spring:
One may think that invoking a method will automatically implement cross-cutting concerns but that is not the case. Just invocation of the method does not invoke the advice(the job which is meant to be done). Spring uses proxy based mechanism i.e. it creates a proxy Object which will wrap around the original object and will take up the advice which is relevant to the method call. Proxy objects can be created either manually through proxy factory bean or through auto proxy configuration in the XML file and get destroyed when the execution completes. Proxy objects are used to enrich the Original behaviour of the real object.
Common terminologies in AOP:
- Aspect: The class which implements the JEE application cross-cutting concerns(transaction, logger etc) is known as the aspect. It can be normal class configured through XML configuration or through regular classes annotated with @Aspect.
- Weaving: The process of linking Aspects with an Advised Object. It can be done at load time, compile time or at runtime time. Spring AOP does weaving at runtime.
Let’s write our first aspect class but before that have a look at the jars required and the Bean configuration file for AOP.
package
com.aspect
import
org.aspectj.lang.annotation.Aspect;
import
Java.lang.RuntimeException;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
// Logging class is anotated with @Aspect
// and will contain advices.
@Aspect
class
Logging {
}
// The class ImplementAspect
// contains method Aspectcall
// and the advices will be applied
// on that method for demo.
public
class
ImplementAspect {
public
static
void
main(String args[])
{
Scanner sc =
new
Scanner(System.in);
System.out.println(
"my first aspect"
);
// **Add beanconfiguration file
// in your programme when executing.**
ApplicationContext ctx
=
new
ClassPathXmlApplicationContext(
"beanconfigfile.XML"
);
ImplementAspect call
= (ImplementAspect)ctx.getbean(
"aspect"
);
System.out.println(
"enter an integer"
);
int
a = sc.nextInt();
if
(a ==
1
) {
throw
new
RuntimeException(msg);
}
else
{
call.aspectCall();
}
call.myMethod();
}
public
void
aspectCall()
{
System.out.println(
"Applying advices"
+
" for the first time"
);
}
public
void
myMethod()
{
System.out.println(
"This is an"
+
" extra method"
);
}
}
- Advice: The job which is meant to be done by an Aspect or it can be defined as the action taken by the Aspect at a particular point. There are five types of Advice namely: Before, After, Around, AfterThrowing and AfterReturning. Let’s have a brief discussion about all the five types.
Types of Advices:
- Before: Runs before the advised method is invoked. It is denoted by @Before annotation.
- After: Runs after the advised method completes regardless of the outcome, whether successful or not. It is denoted by @After annotation.
- AfterReturning: Runs after the advised method successfully completes ie without any runtime exceptions. It is denoted by @AfterReturning annotation.
- Around: This is the strongest advice among all the advice since it wraps around and runs before and after the advised method. This type of advice is used where we need frequent access to a method or database like- caching. It is denoted by @Around annotation.
- AfterThrowing: Runs after the advised method throws a Runtime Exception. It is denoted by @AfterThrowing annotation.
Let’s implement all the five pieces of advice in our Aspect class Logger
// Program to show types of Advices @Aspect class Logging { // Implementing all the five pieces of advice // to execute AfterThrowing advice enter integer value as 1. // **Before** @Before ( "execution(public void com.aspect.ImplementAspect.aspectCall())" ) public void loggingAdvice1() { System.out.println( "Before advice is executed" ); } // **After** @After ( "execution(public void com.aspect.ImplementAspect.aspectCall())" ) public void loggingAdvice2() { System.out.println( "Running After Advice." ); } // **Around** @Around ( "execution(public void com.aspect.ImplementAspect.myMethod())" ) public void loggingAdvice3() { System.out.println( "Before and After invoking method myMethod" ); } // **AfterThrowing** @AfterThrowing ( "execution(" public void com.aspect.ImplementAspect.aspectCall()) ") public void loggingAdvice4() { System.out.println( "Exception thrown in method" ); } // **AfterRunning** @AfterReturning ( "execution(public void com.aspect.ImplementAspect.myMethod())" ) public void loggingAdvice5() { System.out.println( "AfterReturning advice is run" ); } } |
Let’s see what does a joinpoint do in our @Aspect class(Logger)
// Program to show JoinPoints @Aspect class Logging { // Passing a JoinPoint Object // into parameters of the method // with the annotated advice // enables to print the information /// when the advice is executed // with the help of toString() method // present in it. @Before ( "execution(public void com.aspect.ImplementAspect.aspectCall())" ) public void loggingAdvice1(JoinPoint joinpoint) { System.out.println( "Before advice is executed" ); System.out.println(joinpoint.toString()); } } |
// Program to shgw PointCuts @Aspect class Logging { // pointcut() is a dummy method // required to hold @Pointcut annotation // pointcut() can be used instead of writing line 1 // whenever required, as done in line 4. // This prevents a repetition of code. @Pointcut ( "execution(public void com.aspect.ImplementAspect.aspectCall())" ) // line 1 public void pointCut() { } // pointcut() is used to avoid repetition of code @Before ( "pointcut()" ) public void loggingAdvice1() { System.out.println( "Before advice is executed" ); } } |
Please Login to comment...