Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

Introduction to Spring AOP

4.91/5 (9 votes)
31 May 2010CPOL14 min read 67.3K   1.4K  
This article will show the basics and how to use Spring AOP easily, by using some tools such Eclipse, Maven, Spring AOP version 2.5, etc.

Contents

Introduction

This is my second article about Spring Aspect Oriented Programming. This article will show the basics and how to use Spring AOP easily, by using some tools such Eclipse, Maven, Spring AOP version 2.5, etc.

Wait! Why Spring AOP and not full AspectJ?

“Use the simplest thing that can work. Spring AOP is simpler than using full AspectJ as there is no requirement to introduce the AspectJ compiler / weaver into your development and build processes. If you only need to advise the execution of operations on Spring beans, then Spring AOP is the right choice. If you need to advise objects not managed by the Spring container (such as domain objects typically), then you will need to use AspectJ. You will also need to use AspectJ if you wish to advise join points other than simple method executions (for example, field get or set join points, and so on).” - from http://static.springsource.org/spring/docs/2.5.x/reference/aop.html.

After reading the above, you will know the answer to the question! We just need a very simple framework to start AOP. The best choice is the popular one (so it is easier to find someone who can help us ^_^”).

Let's start on Aspect Oriented Programming! But you need to know that I'll only use Spring XML configuration – this maybe the hard way, but it's fun!

What is Aspect Oriented Programming

“Aspect-oriented programming entails breaking down program logic into distinct parts (so-called concerns, cohesive areas of functionality). All programming paradigms support some level of grouping and encapsulation of concerns into separate, independent entities by providing abstractions (e.g., procedures, modules, classes, methods) that can be used for implementing, abstracting, and composing these concerns. But some concerns defy these forms of implementation, and are called crosscutting concerns because they "cut across" multiple abstractions in a program.” - from http://en.wikipedia.org/wiki/Aspect-oriented_programming#Overview

Distinct parts? Abstractions, Multiple abstractions? Crosscutting concerns? Now your head hurts, and you've trouble understanding AOP – don't worry – this can be simplified:

AOP is like Triggers in programming languages such as Perl, .NET, Java and others.

That's easy, right? Can see a blurred little gray light in the AOP way?

Maybe you have learned a bit about SQL and you've heard about Procedures and Triggers:

  • In SQL, you create a Trigger for a table or view.
  • Your Triggers will be for a specific action (insert, update, etc...).
  • And executed at a chosen time (for, after, etc.)

AOP has similar things:

  • You create something called “Aspect”.
  • Your “Aspect” will be executed by checked something called “Pointcut”.
  • Also executed at a chosen moment (before, after, around, etc...).

This is AOP, but you need to know the AOP terms and definitions, such OO-Style (package, class, method, etc.).

Terms & Definitions

As for every concept, AO-Style also has its terms that you need to know a bit about before starting.

  • Concern: This is a battlefield, any interest area, any Use Case (in UML), something/some-area that interested you and that you want to change, like a classical use case as “payment”, “users managements” and many others.
  • Crosscutting concern: This a concern that can affect the entire application and should be centralized in one location in code as possible, such as “authentication” or “logging”.
  • Join Point: A point during the execution of a program, such as the execution of a method or the handling of an exception.
  • Aspect: Is a module that encapsulates a concern. An aspect is composed of Pointcuts, advice bodies, and inter-type declarations. In some approaches, an aspect may also contain classes and methods.
  • Pointcut: A predicate that matches Join Points.
  • Advice: Action taken by an Aspect at a particular Join Point in a desired moment - “before”, “after”, etc.

That is not all the AO-Style terms, but just those we need for starting; for more Spring AOP terms, you can check out http://static.springsource.org/spring/docs/2.5.x/reference/aop.html.

Pointcut! What is it?

Pointcut is a predicate that matches Join Points. This has a very similar syntax style like pattern matching (for Perl programmers) or like Regular Expressions. This predicate or expression matches, for example, a method with a certain name. Example (pointcut for all methods whose names begin with 'list'):

execution ( * adrabi.codeproject.*.GamesImpl.list*( .. ) )

All methods in the class GameImpl that have names starting with 'list' and has any type of parameter.

/!\ Ops! I forget to tell you that Spring AOP is limited only to public methods in beans, unlike AspectJ. You don't have any problems with that, do you?

Seriously, Pointcut is an important part in Aspect. An advice can't be triggered or executed without matching a right Pointcut, or you won't get the desired results.

But, wait man! Why have you started by writing execution( )? Can you show us a real example?

Firstly, this is a real example:

XML
<aop:config> 
    <aop:pointcut id="gamesService" 
       expression="execution(* com.xyz.myapp.service.*.*(..))" /> 
</aop:config>

Secondly, in our case, execution() is necessary. It's a pointcut type or (pointcut designator). Additionally, pointcut isn't limited to a single execution(). You can combine several of them using AND “&&”, OR “||”, and Negated “!”. Surprised?

Now it is time to prepare yourself to start Spring AOP by configuring your environment.

Environment Configuration

Finally! the real examples in action. Try to prepare a very delicious cup of coffee and come back!

You need to install Maven and SpringIDE in Eclipse by following this article: “Pivot 1.4, Spring and Hibernate is my RPG Game” - http://www.codeproject.com/KB/java/PivotSpringHibernateGame.aspx (you need to just read the environment configuration, and come back as a winner).

Now you know how to install anything in Eclipse – very nice – and you need to install Eclipse TDTD for the monitoring and views execution flows. It's not really needed, but the best way to understand is to view “how objects” interact.

Image 1

Installing Eclipse TDTD

Image 2

TDTD example for classes interaction

This is not hard at all. You just need to open the configuration file in your brain and change the variable “use_imagination = 0” to “use_imagination = 1” :D Just kidding.

Now, time to start coding.

Advises! Before, After, and Around

After the configuration is done, we will start coding examples. For each example, we create a unique project, and we use the pointcut type “execute()”. We will see the other types later. By using Maven, we don't need a specific configuration for every project; the same configuration can be used for all the projects.

Additionally, you need to know how to create a Maven project and add it as a Spring Project Nature (http://www.codeproject.com/KB/java/PivotSpringHibernateGame.aspx).

This is a POM configuration for all projects:

XML
<build> 
    <plugins> 
        <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <configuration> 
                <target>1.5</target> 
                <source>1.5</source>
            </configuration> 
        </plugin> 
    </plugins> 
</build> 
<dependencies> 
    <dependency> 
        <groupId>org.springframework</groupId> 
        <artifactId>spring-aop</artifactId> 
        <version>2.5.6</version> 
    </dependency> 
    <dependency> 
        <groupId>org.springframework</groupId> 
        <artifactId>spring-context</artifactId>
        <version>2.5.6</version> 
    </dependency>
    <dependency>
        <groupId>aspectj</groupId> 
        <artifactId>aspectjweaver</artifactId> 
        <version>1.5.4</version> 
        <scope>compile</scope> 
    </dependency> 
</dependencies>

Before Advice

What' do we do?

We simulate a simple CRUD application for hardwares by using:

  • An interface for service called: HardwareService.java
  • A class for implementing the interface called: HardwareImpl.java
  • A simple class entity called: Hardware.java
  • A class for creating methods for Pointcuts called: HardwareServicePointcuts.java
  • And a class for executing the application called: Main.java
  • Plus Spring configuration file called: application.xml

with the objective to apply three Aspects for the Hardware service (HardwareImpl.java) in advice “before”. And we study the results, and each Aspect has a unique pointcut that uses a unique method in the Hardware service pointcuts (HardwareServicePointcuts.java). The pointcut's objectives are:

  • Pointcut for triggering method “beforeAnyMethodStartedWithList” within any method in the Hardware service, with a name beginning with 'list begin executing'.
  • Pointcut for triggering method “beforeRemove” within the method “remove” begins executing.
  • Pointcut for triggering method “beforeIfNotSaveMethod” within any method not named “save” in the Hardware service begins executing.

Are the objectives clear? Let's study the results and output, but before we do it, I'll paste here just the interested parts in the source:

Java
public interface HardwareService 
{ 
      /** 
      * Save new Hardware 
      * @param hw 
      * @return 
      */ 
      public Hardware save( Hardware hw ); 
      
      /** 
      * Remove Hardware 
      * @param hw 
      */ 
      public void remove( Hardware hw ); 
      
      /** 
      * Get Hardware by id 
      * @param id 
      * @return 
      */ 
      public Hardware get(int id); 
      
      /** 
      * Get list of all Hardware 
      * @return 
      */ 
      public List<Hardware> listAll(); 
      
      /** 
      * Get list of Hardware by vendor 
      * @param vendor 
      * @return 
      */ 
      public List<Hardware> listByVendor(String vendor); 
}

This is the Hardware service (HardwareService.java):

Java
public class HardwareServicePointcuts 
{ 
      /** 
      * Pointcut for any method in bean Hardware service his name started with 'list' 
      */ 
      public void beforeAnyMethodStartedWithList() 
      { 
        System.out.println("*** Some methods started with 'list' has " + 
                           "begin executing now! ***"); 
      } 
      
      /** 
      * Pointcut for method remove only in bean Hardware serive 
      */ 
      public void beforeRemove() 
      { 
        System.out.println("*** Method 'remove' has begin executing now! ***"); 
      } 
      
      /** 
      * Pointcut for any method not named 'save' in bean hardware service 
      */ 
      public void beforeIfNotSaveMethod() 
      { 
        System.out.println( "*** Method 'save' hasn't begin executing yet! ***" ); 
      } 
}

This is the method that will be triggered if the Pointcuts match.

XML
<aop:config> 
    <aop:aspect id="anyMethodStartedWithList" ref="hardwareServicePointcuts"> 
        <aop:before method="beforeAnyMethodStartedWithList" 
            pointcut="execution(* adrabi.codeproject.*.*.*.HardwareImpl.list*(..) )" /> 
    </aop:aspect> 

    <aop:aspect id="MethodRemove" ref="hardwareServicePointcuts"> 
        <aop:before method="beforeRemove" 
           pointcut="execution(* adrabi.codeproject.*.*.*.
                     HardwareImpl.remove(adrabi.*.*.*.*.Hardware) )" /> 
    </aop:aspect> 

    <aop:aspect id="notMethodSave" ref="hardwareServicePointcuts"> 
        <aop:before method="beforeIfNotSaveMethod" 
           pointcut="!execution(* adrabi.codeproject.*.*.*.HardwareImpl.save(..) )" /> 
    </aop:aspect> 
</aop:config>

And this is a configuration for Spring AOP. You will notice three Aspects. Each Aspect has an advice “before”, and for each Advice, there is a pointcut. Each pointcut tries to match something.

pointcut="!execution(*adrabi.codeproject.*.*.*.HardwareImpl.save(..) )"

Did you notice a negation “!” before “execution(..)”? This confirms what I motioned in the previous chapters.

Now we profile the application main (in the Main class, right click > in the context menu > click Profile As > Java Application):

Java
public static void main(String[]$) 
{ 
    //init Spring configuration 
    ApplicationContext context = 
      new ClassPathXmlApplicationContext("application.xml"); 
    HardwareService hds = (HardwareService) context.getBean("hardwareService"); 
    
    /*###############[ -- any method started with 'list' -- ]#################*/ 
    System.out.println("\n\n###############[ -- any method " + 
                       "started with 'list' -- ]#################"); 
    //~ 
    List<Hardware> list = hds.listAll(); 
    for( Hardware h : list ) 
    { 
                  System.out.println( h ); 
    } 
    //~ 

    /*###############[ -- method named 'remove' -- ]#################*/ 
    System.out.println("\n\n###############[ -- method " + 
                       "named 'remove' -- ]#################"); 
    //~ 
    hds.remove( hds.get(2) ); 
    //~ 
    
    
    /*###############[ -- method named 'save' -- ]#################*/ 
    System.out.println("\n\n###############[ -- method " + 
                       "named 'save' -- ]#################"); 
    //~ 
    hds.save( new Hardware(4, 5454477877213l, "vendor #4") ); 
    for( Hardware h : list ) 
    { 
                  System.out.println( h ); 
    } 
    //~ 
}

Image 3

After the profiling finishes successfully, we get a nice output that we compare with the class interactions:

###############[ -- any method started with 'list' -- ]################# 
*** Some methods started with 'list' has begin executing now! *** 
*** Method 'save' hasn't begin executing yet! *** 

Hardware :: Identify [1], Serial number [1234567890254] and Vendor [vendor #1] 
Hardware :: Identify [2], Serial number [6545665661545] and Vendor [vendor #2] 
Hardware :: Identify [3], Serial number [1545422984548] and Vendor [vendor #3] 

###############[ -- method named 'remove' -- ]################# 
*** Method 'save' hasn't begin executing yet! *** 
*** Method 'remove' has begin executing now! *** 
*** Method 'save' hasn't begin executing yet! *** 
 
###############[ -- method named 'save' -- ]################# 
Hardware :: Identify [1], Serial number [1234567890254] and Vendor [vendor #1] 
Hardware :: Identify [3], Serial number [1545422984548] and Vendor [vendor #3] 
Hardware :: Identify [4], Serial number [5454477877213] and Vendor [vendor #4]

Now we open the profile report with the “class interactions”:

Image 4

We compare the first Aspect “any method starting with 'list' ” and this is a part from the sequence diagram:

Image 5

From the diagram, we conclude that matches are 100.1 % output results. You see two methods “beforeAnyMethodStartedWithList” and “beforeIfNotSaveMethod” has executed before the method “listAll” in the HardwareImpl class.

Remember, we've created the Aspect for the bean/class HardwareImpl (HardwareImpl.java).

/!\ Ops! I forgotto tell you, the Spring triggers and/or executes aspects by the order in the configuration file.

If we've the configuration below, the results will be different from the last profiling. Try it and you will see the difference:

XML
<aop:config> 
    <aop:aspect id="MethodRemove" ref="hardwareServicePointcuts"> 
        <aop:before method="beforeRemove" 
          pointcut="execution(* adrabi.codeproject.*.*.*.
                    HardwareImpl.remove(adrabi.*.*.*.*.Hardware) )" /> 
    </aop:aspect> 
    
    <aop:aspect id="notMethodSave" ref="hardwareServicePointcuts"> 
        <aop:before method="beforeIfNotSaveMethod" 
           pointcut="!execution(* adrabi.codeproject.*.*.*.HardwareImpl.save(..) )" /> 
    </aop:aspect> 

    <aop:aspect id="anyMethodStartedWithList" ref="hardwareServicePointcuts"> 
        <aop:before method="beforeAnyMethodStartedWithList" 
          pointcut="execution(* adrabi.codeproject.*.*.*.HardwareImpl.list*(..) )" /> 
    </aop:aspect> 
</aop:config>

Maybe, the rest is fine and clear? Ijust want to clarify why we've the aspect for the method named 'remove' twice:

###############[ -- method named 'remove' -- ]################# 
*** Method 'save' hasn't begin executing yet! *** 
*** Method 'remove' has begin executing now! *** 
*** Method 'save' hasn't begin executing yet! ***

As you can see in the Main class:

Java
/*###############[ -- method named 'remove' -- ]#################*/ 
System.out.println("\n\n###############[ -- method " + 
                   "named 'remove' -- ]#################"); 
//~ 
hds.remove( hds.get(2) ); 
//~

Just try to read this code carefully and slowly: “hds.remove( hds.get(2) );”. We've two methods here: first “get”, and second “remove”. “get” is triggered for aspect n°3 because its name is different from “save” and “remove”.

The next advice is the opposite of before, and we call it “after”.

After Advice

What do we do here?

We simulate a simple authentication system by using:

  • An interface for service called: AuthenticationService.java
  • A class for implementing the interface called: AuthenticationImpl.java
  • A class for creating the methods for the Pointcuts called: AuthenticationServicePointcuts.java
  • And a class for executing the application called: Main.java
  • Plus the Spring configuration file called: application.xml

With objectives similar to the advice “before”, we've just two Aspects and two Pointcuts:

  • Pointcut for triggering method “afterUsernameOrPassword” within the method “userName” or “password” has finished executing.
  • Pointcut for triggering method “afterLogout” within any method “logout” in Authentication service has finished executing.

We do some steps as advice “before”.

Java
public interface AuthenticationService 
{ 
  /** 
  * Setting a user name for authentication 
  * @param userName 
  */ 
  public void userName(String userName); 
  
  /** 
  * Setting a password for authentication 
  * @param password 
  */ 
  public void password(String password); 
  
  /** 
  * Try to log-in 
  * @return 
  */ 
  public boolean login(); 
  
  /** 
  * Try to log-out 
  * @return 
  */ 
  public boolean logout(); 
}

This is the Authentication service:

Java
public class AuthenticationServicePointcuts 
{ 
  /** 
  * Pointcut for methods userName() or password() 
  */ 
  public void afterUsernameOrPassword() 
  { 
      System.out.println("*** username or password method has exected ***"); 
  } 
  
  /** 
  * Pointcut for method logout 
  */ 
  public void afterLogout() 
  { 
      System.out.println( "*** you've logout now! see you later, bye! ***" ); 
  } 
}

This is a method that will be triggered if Pointcuts match:

XML
<aop:config> 
    <aop:pointcut id="p_usernameOrPassword" 
       expression="execution(* userName(..)) or execution(* password(..))" /> 
    <aop:pointcut id="p_logout" expression="execution(* logout())" /> 

    <aop:aspect id="afterUsernameOrPassword" ref="authServicePointcuts"> 
       <aop:after method="afterUsernameOrPassword" pointcut-ref="p_usernameOrPassword"/> 
    </aop:aspect> 

    <aop:aspect id="afterLogout" ref="authServicePointcuts"> 
       <aop:after method="afterLogout" pointcut-ref="p_logout"/> 
    </aop:aspect> 
</aop:config>

You can see two things have changed:

  • Firstly, we've created a separated Pointcut.
  • Secondly, in advice “after”, we don't use the parameter “pointcut” as advice “before” but has replaced it with “pointcut-ref”.

Also, you will notice in pointcut n°1 “usernameOrPassword”, I've used “or ”:

expression="execution(* userName(..)) or execution(* password(..))"

Spring AOP support both expressions “OR” and “||”; you've a choice.

We profile the main application:

Java
public static void main(String[]$) 
{ 
    //init Spring configuration 
    ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); 
    AuthenticationService auth = (AuthenticationService)context.getBean("authService"); 

    auth.userName("adrabi"); 
    auth.password("no-password"); 
    System.out.println( "Login results is : " + auth.login()); 
    System.out.println( "Logout results is : " + auth.logout()); 
}

And we get a nice output:

*** username or password method has exected *** 
*** username or password method has exected *** 
Login results is : true 
*** you've logout now! see you later, bye! *** 
Logout results is : true 

Now, we open the profile report with “UML 2 class interactions” and we can see this part from the sequence diagram:

Image 6

Perfect, really similar to the output. We can see in both methods “userName” and “password”, the method “afterUsernameOrPassword” was triggered after execution finishes.

We jump to the last advice but not the least.

Around Advice

What do we do here?

We simulate a simple serial system crack by using:

  • An interface for the service called: SerialService.java
  • A class for implementing the interface called: SerialImpl.java
  • A class for creating methods for Pointcuts called: SerialServicePointcuts.java
  • And a class for executing the application called: Main.java
  • Plus a Spring configuration file called: application.xml

With objectives similar to the advice “before”, we use two Pointcuts for cracking a serial number system:

  • Pointcut for triggering the method “aroundCheckSerialNumber” to replace the method “checkSerialNumber”.
  • Pointcut for triggering the method “aroundSendHasActived” to replace the method “sendSerialHasActived”.

We do some steps as in the advice “before”.

Java
public interface SerialService 
{ 
  /** 
  * Check serial number is valid 
  * @param serial 
  * @return 
  */ 

  public boolean checkSerialNumber(String serial); 
  
  /** 
  * Send serial is actived to vendor 
  */ 
  public void sendSerialHasActived(); 
}

This is the Serial service:

Java
public class SerialServicePointcuts 
{ 
  /** 
  * Around and Stop "CheckSerialNumber" method to be executed 
  * 
  * @param joinPoint 
  */ 
  public boolean aroundCheckSerialNumber( ProceedingJoinPoint joinPoint ) 
  { 
    System.out.println( "*** The method [" + joinPoint.getSignature().getName() + 
                        "] has been cracked ^_^ ***" ); 
    return true; 
  } 
  
  /** 
  * Around and Stop "SendIsHasActived" method to be executed 
  * 
  * @param joinPoint 
  */ 
  public void aroundSendHasActived(ProceedingJoinPoint joinPoint) 
  { 
    System.out.println( "*** The method [" + 
                        joinPoint.getSignature().getName() + 
                        "] has been cracked ^_^ ***" ); 
  }
}

This is a method that will be triggered if the Pointcuts match:

XML
<aop:config> 
    <aop:aspect id="aroundCheckSerialNumber" ref="serialServicePointcuts"> 
        <aop:around method="aroundCheckSerialNumber" 
                pointcut="execution(* checkSerialNumber(..))"/> 
    </aop:aspect> 
    <aop:aspect id="aroundSendHasActived" ref="serialServicePointcuts"> 
        <aop:around method="aroundSendHasActived" 
                pointcut="execution(* sendSerialHasActived(..))"/> 
    </aop:aspect> 
</aop:config>

This is our evil Spring AOP configuration ^_^ to crack the serial number system and to stop the serial number being sent to the vendor.

You can also comment it and see what results can surprise you.

Now we profile the Main class:

Java
public static void main(String[]$) 
{ 
    //init Spring configuration 
    ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); 
    SerialService serial = (SerialService) context.getBean("serialService"); 
    
    //serial for test 1893-5714-6364 
    if( serial.checkSerialNumber(null) ) 
    { 
        serial.sendSerialHasActived(); 
    } 
}

And we get a very nice output:

*** The method [checkSerialNumber] has been cracked ^_^ ***
*** The method [sendSerialHasActived] has been cracked ^_^ ***

Hurry up to view the class interactions:

Image 7

You can see in the sequence diagram that the methods “checkSerialNumber” and “sendSerialHasActived” have been replaced by “aroundCheckSerialNumber” and “aroundSendHasActived”. That is cool, right? Personally, the “around” advice is my preferred one.

I hope you've enjoyed the classical advises “before”, “after” and “around”.

Other Advises

I'm so tired, I can't create more projects for the last two advises “after returning” and “after throwing”. You now know how to create your own Aspects and now you know about Spring AOP too. I'll just introduce them:

  • “after returning” advice: Advice to be triggered/executed after a join point completes normally: for example, if a method returns without throwing an exception.
  • “after throwing” advice: Advice to be triggered/executed if a method exits by throwing an exception.

It's easy to understand: “after returning” for after successful “return” in any method, and “after throwing” for after any exception in a method that causes the method to exit. But, where is the place for an “after” advice between them? “after” advice is a full finished method; in other words:

“after” advice = “after returning” advice + “after throwing” advice.

Now you can create your own examples for them by using one of the preview projects; refer to the documentation.

Parameters in Battlefield

We never introduced parameters in AOP so far, and this is the right time to discuss a bit about them. Can we pass parameters from a JoinPoint to methods triggered/executed? Yeah, we can do it easily! I'll show you two methods for passing parameters.

Do we pass them using Spring XML configuration? Normally, we use the Spring XML configuration. What do we do?

We simulate a simple search engine for the Manga and Anime episodes and save the queries by using:

  • An interface for the service called: SearchService.java
  • A class for implementing the interface called: SearchImpl.java
  • A class for creating methods for Pointcuts called: SearchServicePointcuts.java
  • And a class for executing the application called: Main.java
  • Plus a Spring configuration file called: application.xml

To pass parameters form JoinPoints to the triggered/executed method with two Pointcuts linked to the advice “after”:

  • Pointcut for triggering method “afterBingSearch” within the method “bingSearch” has finished executing.
  • Pointcut for triggering method “afterGoogleSearch” within any method “googleSearch” in the Authentication service has finished executing.
Java
public interface SearchService 
{ 
  /** 
  * Bing search 
  * 
  * @param query 
  * @param cookie 
  */ 
  public void bingSearch(String query, String cookie); 

  /** 
  * Google search 
  * 
  * @param query 
  * @param cookie 
  * @param userId 
  */ 
  public void googleSearch(String query, String cookie, String userId); 
}

This is the Search service source code:

Java
/** 
* Save Bing search query 
* 
* @param jp 
*/ 
public void afterBingSearch(JoinPoint jp) 
{ 
    System.out.println( "*** Save Bing search : [query : " + jp.getArgs()[0] + 
                        ", cookie : " + jp.getArgs()[1] + "] ***" ); 
} 

/** 
* Save Google search query 
* 
* @param query 
* @param cookie 
* @param userId 
*/ 
public void afterGoogleSearch(String query, String cookie, String userId) 
{ 
    System.out.println( "*** Save Bing search : [query : " + query + 
                        ", cookie : " + cookie + ", userid : " + userId + "] ***" ); 
}

This is pointcut's source code:

XML
<aop:config> 
    <aop:aspect id="afterBingSearch" ref="seachServicePointcuts"> 
        <aop:after method="afterBingSearch" pointcut="execution(* bingSearch(..))"/> 
    </aop:aspect> 

    <aop:aspect id="afterGoogleSearch" ref="seachServicePointcuts"> 
        <aop:after method="afterGoogleSearch" 
          pointcut="execution(* googleSearch(..)) and args(query,cookie,userId)"/> 
    </aop:aspect> 
</aop:config>

We try to pass parameters in two ways:

  • Firstly, by using the “bingSearch” method parameter type “JoinPoint”
  • Secondly, by binding parameters with args(..) in the “googleSearch” method

Without profiling this time, we just need to run our Main class:

Java
public static void main(String[] $) 
{ 
    // init Spring configuration 
    ApplicationContext context = new ClassPathXmlApplicationContext( 
                                "application.xml"); 
    SearchService search = (SearchService) context.getBean("searchService"); 
    
    search.bingSearch("ONE PIECE", "some-cookie"); 
    search.googleSearch("Bleach", "some-cookie", "no-userId"); 
}

And finally, we get a nice output and you can see that the parameters has really been passed from the JoinPoints to the triggered methods.

One Piece 452 
One Piece 451 
*** Save Bing search : [query : ONE PIECE, cookie : some-cookie] *** 
Bleach Episode 271 
Bleach Episode 270 
*** Save Bing search : [query : Bleach, cookie : some-cookie, userid : no-userId] ***

I'll finish this article by showing you other Pointcut types.

List of Other Pointcut Types

Here is the rest of the Pointcuts list that can you use in the XML configuration:

  • within: Limits matching join points within certain types (simply the execution of a method declared within a matching type when using Spring AOP).
  • this: limits matching join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type.
  • target: limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type.

Conclusion

The objective of this article is to show you how to use Spring AOP and let you familiarize it. Spring AOP can also use “annotations” and support AspectJ. It's not limited to XML configuration. I just mean to use XML only.

  • AOP is just triggers.
  • Spring AOP can use five types for advises (before, after, around, after returning, and after throwing).
  • Spring AOP is not limited to XML configuration.

I will let you discover Spring AOP annotations by yourself. Thank you for passionately reading my article, and thank you for any corrections and suggestions.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)