There are certain activities like logging, security, caching, transaction management etc. that are applicable to multiple objects in a software system. Such activities are called
. Typically, although these
concerns are conceptually separate from the applicationï¿½s business logic, the code that handle the
concerns is often intermixed with that of the business logic.
This violates the basic design principle of high cohesion and must be avoided.
In object oriented programming, re-use is achieved using inheritance or delegation. But inheritance may lead to brittle hierarchies while delegation may involve complicated calls to the delegate.
For specific cases where code re-use needs to be achieved for
concerns, Aspect Oriented programming provides a very good alternative to inheritance and delegation.
In Aspect Oriented Programming, the code to be re-used is placed in one place but it is invoked declaratively by defining how and where this common functionality should be executed without having to modify the class to which these
concerns are applied.
The following are some the terms associated with Aspect Oriented Programming
|Cross Cutting Concerns||There are certain activities like logging, security, caching, transaction management etc. that are applicable to multiple objects in a software system|
|Advice||The common functionality that handles the cross cutting concern|
|Pointcut||The classes and methods where the Advice needs to be applied|
|Join Point||The exact point in execution (before method call, after method call, exception throw, field modified, etc.) where the advice needs to be applied|
|Aspect||A combination of Advice, Pointcut and Join Point|
|Weaving||The process of applying Aspect to a target object to create a new proxied object|
An advice can be applied at various stages of method execution.
- After (aop:after) – The advice is applied after a method returns. The method may have returned successfully or may have thrown an error
- After Returning (aop:after-returning) – The advice is applied after a method return successfully.
- After throwing (aop:after-throwing) – The advice is applied after a method throws an error
- Around (aop:around) – This is probably the most interesting case and we shall cover this with an example below. This method is quite useful since it has access to the state of the object before and after the execution of the method.
- Before – The advice is applied before entering a method.
The pointcut can be defined using the following syntax
– tells that the advice needs to the triggered on the method execution.
– tells that the method may have any return type.
The rest of the text
gives the fully qualified class name and the method to which the advice applies.
The two dots in the bracket specify that the method may take in any argument.
A pointcut may have various
such as args() (limits matches to methods whose argument types matches the argument specified here), within() (limit matches to methods of objects of particular type) etc.
It is also possible to combine designators using the ‘&&’, ‘||’ or ‘!’ operator. It is also possible to limit pointcuts to particular beans using the bean() designator or ignore a particular bean using the !bean() designator.
Sample Program Overview
The sample program explains how AOP works in practice. We demonstrate an around advice. It is natural to think of around advice as a combination of a before and an after advice, however there is a big difference. In an around advice the advice gains control of the execution. Think of it as a wrapper or a proxy class around the class whose method is advised. The control reaches the around advice’s method. The advice in turn calls the proceed() method that runs the method that is advised. In the example below, we want to calculate the time it takes the personservice to add a person. The advice is woven around the addPerson method. Notice the line proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); This line calls the addPerson method and the method returns in the advice itself. You may notice that since advice is in control of the execution, the program may hang if the proceed method is never called.
We will create the Person class with members as name and email.
We will create the PersonService class with method addPerson() .
We will create the MethodExecutionTimeAdvice class with method calculateMethodExecutionTime(ProceedingJoinPoint proceedingJoinPoint)
We will also create the spring-config.xml
Finally, we will test our setup using TestAopXml class which will load Spring context and get a reference to personService class. We will print the time it takes to run the addPerson() method.
Create the Person (see sample code below).
Create members name and email (see lines 5-6 below)
Create accessor methods for name and email (see lines 11-19 below).
Create the PersonService (see sample code below).
Create addPerson() method which simulates adding of Person to the system (see lines 5-7 below)
Create the MethodExecutionTimeAdvice (see sample code below).
Create calculateMethodExecutionTime() method which takes
as argument (see lines 7-17 below).
Add the logic to calculate the time taken to execute the method (see lines 9, 15 and 16 below).
Invoke the called method (in this case PersonService.addPerson()) using
(see line 11 below).
Create the spring-config.xml file (see below).
Define the XML namespaces for aop schema (sees line 4, 9 and 10)
Declare bean for personService (see line 14 below).
Declare the bean for methodExecutionTimeAdvice (see line 16 below)
Declare the AOP config (see lines 18 – 27 below)
Refer to the methodExecutionTimeAdvice which tells Spring which Advice to use in this Aspect (see line 19 below)
Define the methodExecutionTimePointcut Pointcut (see lines 21-22 below) which tells Spring to invoke the Advice when PersonService.addPerson() is called
tag to let Spring know that the Advice needs to be called when around a method call (i.e. both before and after method call execution)
This demonstrates the usage of XML configuration of Spring AOP
Finally, we need a java program to test the our setup.This is done by TestAopXml (see source code below).
We need to tell Spring framework to use the ‘spring-config.xml’ to load our beans (see line 11 below).
We get the reference to PersonService class through Spring using the bean name ‘personService’ (see line 12 below).
We then create an instance of Person class with its name and email address (see lines 13-15 below).
We access the PersonService.add() method to verify that MethodExecutionTimeAdvice was successfully invoked and that it calculated the time taken to execute the PersonService.add() method (see line 16 below).
This sample program has been packaged as a jar installer which will copy the source code (along with all necessary dependencies) on your machine and automatically run the program for you as shown in the steps below. To run the sample program, you only need Java Runtime Environment (JRE) on your machine and nothing else.
(Alternatively you can go the folder containing the springaopxml-installer.jar and execute the jar using
java -jar springaopxml-installer.jar
This source code for this program is downloaded in the folder specified by you (say, C:\Temp) as an eclipse project called
. All the required libraries have also been downloaded and placed in the same location. You can open this project from Eclipe IDE and directly browse the source code. See below for details of the project structure.