Spring Aop : Basics

Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about program structure. AOP is a technique for augmenting the behavior of objects, methods, and functions non-invasively. AOP allows you to add new behaviors and to combine and modify existing behaviors from the outside. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect.

AOP breaks the program logic into distinct parts (called concerns). It is used to increase modularity bycross-cutting concerns. A cross-cutting concern is a concern that can affect the whole application and should be centralized in one location in code as possible, such as transaction management, authentication, logging, security etc.

Let us take the example of logging. We want this  logMessage() functionality in all your class/objects, thus we will have the same method in all our classes like following.

SpringAop1

This is not a good design as your code is repetative. A generall solution is to take out this logMessage() method and keep it in another object say Logger. Now which ever object requires this functionality, can call the Logger object.

SpringAop2

Problems with above approach :

  • We still need to write the code in all the methods to call the logger object logMessage(). Any changes in future will require changes in all method.
  • Too many relationship (while designing) with the Logger class which actually doesnt have any business logic or is not important.

Ofcourse there are other approaches like using inheritace etc but the basic problems remains the same.

AOP way:

The first step is same. You have a class say LoggingAspect which have a logMessage() method. This class is slightly different from the normal java classes as it is annotated with @Aspect. We will see this later for now lets say that this is our LoggingAspect. Now for other objects to use this Logging Aspect logMessage() method , no code or reference is required to be written in their methods. You will rather have a Aspect Configuration of someking in xml and/or using annotation to tell Spring which methods this aspect applies to.

SpringAop3

 

For understanding better, aspect can be related to triggers in databases, like run this funtion whenever a row gets inserted in a table. Also, servlet/portlet filters can also be related.

Lets get to the code. In addition to the basic spring jars we will need aspectj(aspectjrt ,aspectjweaver, aspectjtools), aopalliance, cglib, asm jars. These can be downloaded here:
AspectJ – http://www.eclipse.org/aspectj/downloads.php
Aopalliance – http://aopalliance.sourceforge.net/
Cglib – http://cglib.sourceforge.net/
Asm – http://asm.ow2.org/

Lets get to the code:

Create a Java Project with Spring (with common-logging jar) and above mentioned libraries. Our overall structure of project will look like this:

SpringAop4

Following are our model classes:
SoftwareDevelopers.java:


package mynotes.aop.model;

public class SoftwareDevelopers {

public String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}

Managers.java:


package mynotes.aop.model;

public class Managers {

public String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}

EmployeeService.java


package mynotes.aop.service;

import mynotes.aop.model.Managers;
import mynotes.aop.model.SoftwareDevelopers;

public class EmployeeService {

private SoftwareDevelopers softwareDevelopers;
private Managers managers;
public SoftwareDevelopers getSoftwareDevelopers() {
return softwareDevelopers;
}
public void setSoftwareDevelopers(SoftwareDevelopers softwareDevelopers) {
this.softwareDevelopers = softwareDevelopers;
}
public Managers getManagers() {
return managers;
}
public void setManagers(Managers managers) {
this.managers = managers;
}

}

spring.xml:


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<bean id="softwareDevelopers" class="mynotes.aop.model.SoftwareDevelopers">
<property name="name" value="developer1"></property>
</bean>
<bean id="managers" class="mynotes.aop.model.Managers">
<property name="name" value="manager1"></property>
</bean>

<bean id="employeeService" class="mynotes.aop.service.EmployeeService"
autowire="byName" />

</beans>

SpringAopMain.java :


package mynotes.aop.main;

import mynotes.aop.service.EmployeeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringAopMain {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
EmployeeService employeeService=context.getBean("employeeService",EmployeeService.class);

System.out.println(employeeService.getSoftwareDevelopers().getName());

System.out.println(employeeService.getManagers().getName());
}

}

On running SpringAopMain you will get the following output:


developer1
manager1

This is just plain core spring where you define your service bean and autowired it to other beans since they have the same name as the attribute. In the main method you get you service bean which get instantiated with respective SoftwareDevelopers and Managers object according to configuration provided in spring.xml and then prints the name.

Now lets say we have a requirement of prining a log message everytime a getter of these atrributes are called. The old way will be write it inside the loggers of somewhere before the the getter called. let do the AOP way. Lets create a LoggingAspect class with a logMessage().

LoggingAspect.java:


package mynotes.aop.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect {

@Before("execution(public String getName())")
public void logMessage(){
System.out.println("Before Logging Aspect from annotation");
}

}

Notice we have annotated the class with @Aspect and the method @Before. The parameter in the method takes a string which is says that run/execute this method everytime a “public String getName()” is called. Add the following entried to your spring.xml to tell spring about this aspect.
Add in spring.xml:


<aop:aspectj-autoproxy />

<bean id="loggingAspect" class="mynotes.aop.aspect.LoggingAspect" />

With autoproxy spring automatically searches the bean which are aspects. Now run SpringAopMain.java again. Output:


Before Logging Aspect from annotation
developer1
Before Logging Aspect from annotation
manager1

As you can see without adding any code to the exsiting classes, we simply added a feature from the outside.

The above approach was by using annotation. Suppose you want to have aspect in your spring.xml instead, we can also do that. Lets create a new class. LoggingAspectXml.java:


package mynotes.aop.aspect;

public class LoggingAspectXml {

public void logMessage(){
System.out.println("Before Logging Aspect from XML");
}

}

Notice it has no aspect related configuration. Just a plain class.

Add the following to spring.xml:


<bean id="loggingAspectXml" class="mynotes.aop.aspect.LoggingAspectXml" />

<aop:config>
<aop:aspect id="loggingAspectXml" ref="loggingAspectXml">
<aop:pointcut id="pointcutId1" expression="execution(public String getName())" />
<aop:before method="logMessage" pointcut-ref="pointcutId1"/>
</aop:aspect>

</aop:config>

Here we have first define the new bean loggingAspectXml. Now using aop:config we define the class we want to use as aspect. Inside aop:aspect we can define out pointcut expression which can later be used by other aop configs.

Lets run SpringAopMain.java again:


Before Logging Aspect from XML
Before Logging Aspect from annotation
developer1
Before Logging Aspect from XML
Before Logging Aspect from annotation
manager1

Now we get both the aspect. One from the annotaion and one from xml. Which senario to use will depend upon your requirements. Ideally annotation are the current trend and makes your code cleanear, however a situation may arise where you want these common methods to be placed in a jar file and this jar file will be referenced by your other projects which in turn can define how they want to use these common non business functionalities accordingly.

Advertisements

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

%d bloggers like this: