AOP in Spring Framework

In the previous article, we have understood How to do configuration using java in the Spring framework you can check it here Java Based Configuration in Spring. In this article, we will understand Aspect-Oriented Programming using a simple example.

There is a number of paradigm in the programming language on which any software or application is built. In that, there is Object Oriented Programming language where every one of us is well aware of because we have learned C++, Java that is based on OOPs Paradigm. In the same way, we have a new paradigm called AOP i.e Aspect-Oriented Programming. 

Note: Paradigm is nothing but the basic style of programming language.

What is Spring AOP?

Spring AOP also plays a vital role in the popularity of the spring framework. The Aspect-Oriented Programming uses aspects in the programming Just like OOPs uses Objects.

  • In this paradigm, the code is broken down into different modules called cross-cutting concerns i.e Modularisation is achieved, where the key unit is called aspect. The cross-cutting concern is separated from the business logic.
  • There are Aspects such as logging, transaction which are not considered as business logic but are required in the code.
  • It is added by adding as advice to the existing code.
  • AOP provides the pluggable way to add this additional concern before, after, or on the actual logic.
  • And, Hence the Modularization is achieved using AOP.

Consider an example, You have to perform logging.

  • If you have to do in every or major part of your program then this would be considered as Model Logic.
  • But as we know, Logging is a way of keeping a record of all data input, processes, data output, and final results in a program, which is a non-functional requirement and hence called a cross-cutting concern.
  • If we use the AOP paradigm, then the domain model of your program will not know about logging and you can plug using the AOP aspect wherever you want.

Let us see some important terminology related to Spring AOP.

Important Terminology of AOP

Aspect

This is a class that contains the cross-cutting requirement. There can be more than one Aspect in the application. This is tagged by @aspect annotation.

Joinpoint

The point in your program where the method executes is called a Joinpoint.

Advice

This is action to be taken either before or after the execution of the method. There are different type of advice:

  • Before: It executes before the joint point. It is denoted by @Before
  • After: It executes after the joining point regardless of the outcomes. It is denoted by @After.
  • After running: It executes after the successful running of joinpoint. It is denoted by @AfterRunning.
  • Around: It executes before and after the joinpoint. It is denoted by @Around.
  • After Throwing: It executes after the joining point throws Runtime Exception. It is denoted by @AfterThrowing.

Pointcut

The pointcut defines a collection of join points that need to be matched before running the advice. It uses the expression language of AOP.

Introduction

It allows us to introduce an additional interface.

Target Object

An object that is being advised by one or more aspects is Target Object.

Weaving

Weaving links aspects with other application types or objects to create an advised object. Spring AOP performs weaving at runtime.

Implementation of Spring AOP

It can be implemented using the following 3 ways:

  1. Spring 1. 2 Old Style.
  2. XML based 
  3. @AspectJ annotation based.

Here, we see using @AspectJ annotation based.

Example to Implement Spring AOP using @AspectJ annotation

Create a Spring Project Go to File> New > Other > Search maven > Select Maven Project > Next > Search Filter org.apche.maven.archetypes/webapp > Next > Enter Group Id & Archetype id > Finish.

We need to add the AspectJ library. Add the following dependencies into pom.xml.

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.7.RELEASE</version>
</dependency>
<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.5</version>
</dependency>
<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
</dependency>

Following is the pom.xml file:

<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>com</groupId>
  <artifactId>AOPExample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>AOPExample</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.3.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.5</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
    </dependency>
  </dependencies>
</project>

Create an Example.java file with three methods:

package com.AOPExample;

public class Example {

  /*
   * TODO: Method 1
   */
  public void method1() {
    System.out.print("Method 1 is invoked....");
  }
  /*
   * TODO: Method 2
   */
  public void method2() {
    System.out.print("Method 2 is invoked....");
  }
  /*
   * TODO: Method 3
   */
  public void method3() {
    System.out.print("Method 3 is invoked....");
  }
  

}

beans.xml

Create a beans.xml to configure the Example.java and The Aspect class that we will create. In the beans.xml file use the <aop:aspectj-autoproxy/> to enable AspectJ support.

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

  <aop:aspectj-autoproxy/>
  <bean id="ex"  class="com.AOPExample.Example"></bean>
  <bean id="AspectClass"  class="com.AOPExample.AspectClass"></bean>
    
  
</beans>

 

Create an Aspect Module:

Declaration: It is the same as the other normal class except that it will have @Aspect annotations like the following:

package com.abc;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class DemoAspectModule {
}

Declaring a pointcut in Aspect Class: It helps to determine the points where the advice should be executed. It is declared like the following:

@Pointcut("execution(* Example.method2*(..))")  //Expression of AOP
  public void logic() {	}  // Where the advice should be executed

Declare Advice in Aspect Class: We can declare any of the five advices that we have discussed above. It is declared like the following:

@Before("logic()")
public void doBeforeTask(){
   ...
}

@After("logic()")
public void doAfterTask(){
   ...
}

Let us see Our Examples Aspect Class:

AspectClass.java

package com.AOPExample;

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 AspectClass {

  @Pointcut("execution(* Example.*(..))")
  public void method2() {	}
  
  @Before("method2()")
  public void myAdvice(JoinPoint  joinPoint) {
    System.out.println("Pluggable code..");
  }
}
  • On line no:11, The pointcut is declared on method2 so that the advice will be called on all methods.
  • On line no:14, Advice is created and It will be called Before the selected method execution.

Now, Create an App.java

  •  Now, create the Object of Application Context, get the bean from it and call the methods.
package com.AOPExample;

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

public class App 
{
    public static void main( String[] args )
    {
      ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
      Example c =  context.getBean("ex",Example.class);
      c.method1();
      c.method2();
      c.method3();
    }
}

Now, Run the App.java and Observe the following output

Pluggable code..
Method 1 is invoked....Pluggable code..
Method 2 is invoked....Pluggable code..
Method 3 is invoked...

Here, we can observe that Advice is called before every method execution. In this way, you can configure the Aspect class according to the need.

Thus, these AOP concepts provide a helpful paradigm to separate the cross-cutting concerns in the application. In the next article, we will understand the JDBC framework in Spring.