http://www.developer.com/lang/article.php/3649681/Modularizing-and-Code-Reuse-Using-AOP.htm
Aspect-Oriented Programming (AOP) is a new exciting paradigm. It is not a competitor to the famous Object-Oriented Programming (OOP), they actually complement each other. It can be considered an extension to OOP. AOP modularizes software applications based on loosely coupled aspects, whereas OOP does it by using Encapsulation, Inheritance, and Polymorphism. AOP is a concept and not bound to any programming language. Software vendors can provide implementation for AOP in any programming language and make it available for the entire software community. Several vendors provide implementations in the Java language for AOP. This article uses the AspectJ implementation of AOP and will attempt to give some insight about code modularity and reuse using aspects. A concern is nothing but a function in a given system. Any system is typically composed of both core and non-core concerns. The non-core concerns such as logging and security are actually the supporting functionalities for the mainstay core functionalities. The core functionality is the one that the system is expected to do. The main job of a non-core concern is to provide some extra functionality such as error handling to the core functionality, which will help in system management. But, in real life, what happens? For instance, take the example of a logging concern. Everyone will try to design in such as way that logging is implemented in a generic way and used for all modules/components of the system. Eventually, what happens? The logging code will cut across almost all modules in the system and become interleaved with the code responsible for core concerns. Thus, the logging concern becomes tightly coupled with the core concerns and becomes inseparable. In the case that any modification/enhancement/removal of logging is required, it will almost become impossible to do so because it involves huge efforts in terms of development and testing time. Here is where AOP pitches in. AOP helps separate the non-core concerns from the core concerns by implementing concerns as aspects. Each aspect is independent and loosely coupled with other aspects in the system. This provides the flexibility for developers to enhance or remove any aspect at a later point in time without affecting the design and current state of the system. Think about another scenario, wherein AOP can really be useful. A developer has put in a lot of effort to implement an excellent business application, test it, and also move it into production systems. Later, he learns that execution of a particular logic in the application consumes more time than he has expected. To unveil the problem, he wants to benchmark the logic. The one option that you could think of is wherever this logic is being called, just put the time stamps before and after invocations to measure the time taken to execute. Assume that it has been used in several places in the application; just think about the amount of effort involved in getting this task done. Huge, right??? AOP helps accomplishing this in a simple, maintainable, loosely coupled and reusable way. The benchmarking logics can be encapsulated separately as an aspect that can be reused for benchmarking other applications. You get the following advantages as you implement benchmarking as an aspect: That's a lot of theory. It's time to get your hands dirty. Take a loan calculator example. Given the principle amount, tenure in months, and the interest rate per annum, the loan calculator should be able to give you the monthly installment that you might need to pay. Please refer to the sample programs to benchmark the loan calculator application. Loan Calculator Loan Client Loan client with benchmarking Please look at LoanClient2.java. The system time stamps have been put before and after invoking the business methods. Because of this ad-hoc method, there are several disadvantages: What you need here is a re-usable, easily manageable and separable programming construct. AOP provides that. In this section, you can see how AOP can be used to benchmark this loan calculator application. AOP can be configured to dynamically pick up the execution points within a program during execution and intercept the methods and fields to get to know what is happening around them. An execution point within a program is called Join Point. For example, calling to a method is a join point. A set of join points is called point cut. You can configure many such point cuts. Advice is an encapsulation of piece of code (in your case, it is benchmarking logic) that you want to execute, when the execution points (in other words, point cuts) are detected during execution. For more information, please refer to www.aspectj.org. You might need to get your hands little dirty before getting AspectJ working. Let me go step by step how to get it done. For your example, you use the AspectJ implementation of AOP. In the sample aspect, you have used "Around" advice and a point cut (whose configuration has been externalized by using aop.xml, which is explained in the next section). Create Aspect: Point cut: The build file has been given; by using it, you can run both flavors of benchmarking. Set the environment variables for Ant and then run "ant" to build and run both flavors. Build.xml Aspect-Oriented Programming has numerous advantages. Some of them are mentioned below: To give fair coverage of the topic I should list any negatives along with all the positives. On the downside, in my opinion, I found the learning curve steep. It takes a little longer to understand the concepts of joint point, advice and annotations style of programming. It also adds some latency to the target application, which might make you feel the performance hit.
Apart from AspectJ, there are other implementations also available. Some of them are Spring, Jboss, and AspectWerks. It's up to you to choose the implementation that is right for you. AOP is easier to understand and implement. It achieves code reuse and modularization at much greater levels. It removes the cross cutting concerns and makes application loosely coupled and maintenance easy. Ayyappan Gandhirajan holds a Master's degree in Software Systems from BITS, Pilani, India and a Bachelor's degree in Electronics & Communication Engineering from MK University, India. He has over eight years of profound software experience in domains of Travel, Telecom/Mobility, and e-commerce and technologies such as Spring, AOP, ESB, Web services, WS Security, and J2EE. He currently works for Perot Systems, India. Before joining Perot, he worked for five years with Hewlett-Packard ISO, India. He can be reached at ayyappan.gandhirajan@ps.net or G_Ayyapparaj@yahoo.com.
Modularizing and Code Reuse Using AOP
December 18, 2006
Crosscutting Concerns
Putting AOP to Practical Use
Conventional way of benchmarking
package sample;
public class LoanCalculator {
public double calculateEMI ( int principle, int tenure,
double interest) {
double emi ;
// calculate the Equated Monthly Installment
return emi;
}
}
package sample;
public class LoanClient {
public double calculate(){
System.out.println("Calculate EMI...");
double installment =
new LoanCalculator().calculateEMI(100000, 60, 9.5);
System.out.println("EMI is - "+ installment);
return installment;
}
public static void main(String[] args){
new LoanClient().calculate();
}
}
package sample;
public class LoanClient2 {
public double calculate(){
long start = System.currentTimeMillis();
System.out.println("Calculate EMI...");
double installment =
new LoanCalculator().calculateEMI(100000, 60, 9.5);
System.out.println("EMI is - "+ installment);
long end = System.currentTimeMillis();
return installment;
}
public static void main(String[] args){
new LoanClient2().calculate();
}
}
The AOP Way of Benchmarking
package aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public abstract class AbstractBenchmarkAspect {
@Pointcut
public abstract void benchmark();
@Around("benchmark()")
public Object executeBenchmarkAdvise(ProceedingJoinPoint jp)
throws Throwable{
long startTime = System.currentTimeMillis();
Object response = jp.proceed();
long endTime = System.currentTimeMillis();
System.out.println("TIME TAKEN (in msecs): "+
(endTime - startTime));
return response;
}
}
<aspectj>
<aspects>
<concrete-aspect
name="aspect.BenchmarkAspect"
extends="aspect.AbstractBenchmarkAspect">
<pointcut name="benchmark"
expression=
"execution(* sample.LoanCalculator.*(..)))" />
</concrete-aspect>
</aspects>
</aspectj>
<project name="aspect" default="run">
<target name="init">
<mkdir dir="build"/>
</target>
<target name="compile" depends="init">
<javac
srcdir="src"
destdir="build"
source="1.5"
debug="true">
<classpath refid="build.classpath"/>
</javac>
</target>
<target name="run" depends="compile">
<echo>========================================</echo>
<echo>Running without aspect...</echo>
<echo>========================================</echo>
<java classname="sample.LoanClient2" fork="true">
<classpath refid="build.classpath"/>
</java>
<echo></echo>
<echo>========================================</echo>
<echo>Running with aspect...</echo>
<echo>========================================</echo>
<java classname="sample.LoanClient" fork="true">
<classpath refid="build.classpath"/>
<jvmarg value="-javaagent:libaspectjweaver.jar"/>
</java>
</target>
<path id="build.classpath">
<pathelement location="build"/>
<pathelement location="bin"/>
<fileset dir="lib">
<include name="*.jar"/>
</fileset>
</path>
</project>
Advantages
Disadvantages
Summary
References
About the Author