Sunday, October 6, 2013

Spring AOP - Part III

For part I, refer to: Spring AOP - Part I
For part II, refer to: Spring AOP - Part II

Continuing further on AOP examples, in this post, we will see how can we pass arguments to the Aspect classes.


Passing parameters to Aspect classes:

In this example, we will write a very basic auditing service, which will store audit details of who accessed a particular service.

The audit details could be stored in database. But that part is not shown here to keep the details simple.

Let us say we have an Account service, which offers CRUD on the account. The username parameter which is the first parameter for all the methods, indicates the user who will perform a CRUD on the account.
public interface AccountService {
    public long createAccount(String username, Account account);
    public void updateAccount(String username, Account account);
    public void deleteAccount(String username, Account account);
}

Define a corresponding AccountServiceImpl which will actually perform the CRUD. (not shown here).

Define an AuditService to define the audit operation and its implementation. Note that the audit service also has a "username" parameter which will passed from the target class (i.e, AccountService). Note that JoinPoint should always be first parameter, followed by the custom arguments.
public interface AuditService {
    public void performAudit(JoinPoint joinPoint,String username);
}
public class AuditServiceImpl implements AuditService{
        public void performAudit(JoinPoint joinPoint,String username) {
                 //log or store in database
        }
}

Spring config xml:

Note the String parameter passed to AccountService methods and the 'username' parameter name within args. This parameter name should match the actual name in AccountService.

<aop:aspect ref="auditService">  
         <aop:pointcut  id ="audit" expression="execution(* com.myorg.service.AccountService.*(String,..)) and args(username,..)"/>
         <aop:before  method="performAudit"  pointcut-ref="audit"/>
</aop:aspect>

AOP Introductions:

We can add new functionality to existing classes by using AOP Introductions. Internally, Spring will invoke these methods through the proxy implementation and this call will not go to the target class.

Lets say we create a new interface AccountAudit to define some special audits related to Account service.
public interface AccountAudit{
    public void performAudit();
}

We will define an implementation for this;
public class AccountAuditImpl implements AccountAudit{
    public void performAudit(){
        //audit
    }
}
We will need AccountService also to implement the same interface using AOP. We need to define this in the spring context xml as below:
<aop:aspect>
   <aop:declare-parents types-matching="com.org.AccountService+"
          implement-interface="com.org.AccountAudit"
          default-impl="com.org.AccountAuditImpl"/>
</aop:aspect>

Now, effectively this means that the AccountService could be type casted to AccountAudit as below and we can invoke the performAudit() method using AccountService reference.

((AccountAudit) accServ).performAudit();


Applications of AOP:


In general, AOP can be best used in logging, security, transaction, auditing.

However, a word of caution while using AOP.  Though AOP is very powerful, avoid using AOP for implementing business logic, as it will result in a maintenance nightmare since it will be hard to figure out that some part of the business logic is in the aspect classes.




No comments:

Post a Comment