Showing posts with label aop-advice. Show all posts
Showing posts with label aop-advice. Show all posts

Monday, 25 April 2011

Need for AOP

Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about program structure. 

Consider a following method code (say in a webservice method):

try{
   //start new session
   //some business logic
   //commit transaction
}catch(Exception ex)
{
   //handle exception
}finally{
   //close session
}
//logging
//return the output


So like this method above, there will be lots of other methods similar to this....But don't you think it will be nice if  we only deal with business logic, rather than writing the repeatative code like handling exceptions, logging,security management, etc. These code tidbits are called concerns or aspects or advices (though described below). These are used interchangeably, though there are slight differences, which we will see in course of time.

So this is where AOP comes into picture. We can simply write our code as a simple business logic, without dealing with above mentioned concerns or repeatative code. For eg. for security checks, you can add the authorization into the execution path with a type of IOC implementation called AOP or aspect oriented programming. 

See Aop introduction

AOP introduction

Need For AOP
First see need for aop.

Defining AOP
Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about program structure.

Aspects
Aspects are concern of the application that apply themselves across the entire system. The SecurityManager is one example of system-wide aspect, as its hasPermissions methods are used by many methods. Other typical aspects include logging, auditing, exception handling, performance monitoring, transaction management. See need for aop . These are also called advice, interceptor or concernts.

Who handles these concerns?
These types of concerns are best left to framework hosting the application, allowing developers to focus more on business logic.

AOP frameworks available
There are lots of frameworks available for AOP in java, and each one calls the concerns with differnt names, written within parenthesis:
  • AOPAlliance API (interceptor)
  • AspectJ (Aspect)
  • Spring AOP (Advice)
  • Spring-AspectJ combination (Aspect)
For AOPAlliance, click here.
AspectJ plugin for eclipse ide can be downloaded from here.
For spring we will see in tutorial continued. Since spring 2.0 AspectJ is the best AOP implementation, so its also combined in spring as told above.

Weaving or interjection
An AOP framework, such as spring AOP will interject or weave aspect code transparently into your domain model at runtime or compile time. This means that while we may have removed calls to the SecurityManager from the Business class, it will be still executed in AOP framework.
The beauty of this technique is that both the domain model (eg. our business code, say BankAccount) and its user or client such as Customer, both are unaware of the enhancement to the code.

What are cross-cutting concerns?

The Separation of Concerns principal states that a concern is any piece of interest or focus in a program. Think about it in terms of a layered architecture with the layers being UI, Business, Service and Data. Each one of these layers is its own concern. These layers are "horizontal".
The UI layer is only concerned with display and user interaction and not with database connectivity; as such, the data layer is not concerned with determining if a user is eligible for a car loan (business rules). When you design your code you usually break up these concerns into their own modules (classes, assemblies, etc).
Logging, security, error handling and caching are also concerns but where do they fit in to this layered architecture? The answer is everywhere. These concerns are "vertical" or "cross-cutting" or "orthogonal" which means they touch each layer. UI needs logging and error handling just as the other layers do too.

More terminology on AOP.


Saturday, 19 March 2011

Implementing @Around advice

To get pre and post processing of calling any function, its good to implement @Around advice.

Consider the following Aspect with around advice:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.util.StopWatch;

@Aspect
public class ProfilingAspect {

@Around("execution(* *(..))")
public Object profile(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch watch = new StopWatch();
watch.start(joinPoint.getSignature().getName());
try {
return joinPoint.proceed(); //calling the target method
}
catch(Exception e) {
throw e;
}
finally {
watch.stop();
System.out.println(watch.prettyPrint());
}
}
}

 

Corresponding config file:



<aop:aspectj-autoproxy />

<bean id="profilingAspect" class="ex7.ProfilingAspect" />
<!--some service class -->
<bean id="customerService" class="service.CustomerServiceImpl" />

Exception handling with AOP

The throws advice is executed when a method throws an exception.

Handling exception by this method saves us from writing repeating try-catch block again and again.

Consider the following java code:

//interface with method throwing exception
public interface BusinessInterface {

public void someBusinessMethod() throws BusinessException;

}
//class implementing it
import org.springframework.jdbc.BadSqlGrammarException;

public class BusinessComponent implements BusinessInterface {

public void someBusinessMethod() throws BusinessException {
//we are raising a different exception to see the aspect coming into action
//assume that you are connecting to the database and something goes wrong
throw new BadSqlGrammarException("","",null);
}
}


So now this business logic may throw exception, and it will be handled by Aspect.


So we have to write handler for this:


import java.util.Locale;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;

@Aspect
public class ExceptionHandler implements MessageSourceAware {

private MessageSource messageSource;

@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}

@AfterThrowing(pointcut="execution(* someBusinessMethod(..))", throwing="ex")
public void handleException(JoinPoint jp, RuntimeException ex) throws Throwable {
System.out.println("Routine exception handling code here.");
System.out.println("Let's see who has raised an exception!");
System.out.println("===================================");
System.out.println(jp.getSignature().getName());
System.out.println("===================================");
throw new BusinessException(messageSource.getMessage(jp.getSignature().getName(), null, Locale.getDefault()));
}
}


Now if we want pre and post analysis of method, @Around advice will be handy for this.


Corresponding config file:



<aop:aspectj-autoproxy />

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="ex6/messages" />
</bean>

<bean id="exceptionHandler" class="com.xxxx.ExceptionHandler" />

<bean id="businessComponent" class="com.xxxx.BusinessComponent" />

Implementing @After and @AfterReturning advice

As we have done @Before, till now, it is also similar to that.

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class LoggingAspect {

@After("bean(*Service)")
public void log(JoinPoint joinPoint) {
System.out.println("log advice got executed after call to method : "+joinPoint.getSignature().getName());
}

@AfterReturning(pointcut="execution(* balance(..)) && args(acno)", returning="balance")
public void validate(JoinPoint joinPoint, long acno, double balance) {
System.out.println("validate advice called after successful return from balance method");
System.out.println("acno passed was "+acno+" and the balance returned was "+balance);
}
}



Spring config file :


<aop:aspectj-autoproxy />

<bean id="loggingAspect" class="ex5.LoggingAspect" />

<bean id="orderService" class="service.OrderServiceImpl" />

<bean id="customerService" class="service.CustomerServiceImpl" />

Named pointcut expression

Sometimes it happens that we may need same pointcut at multiple places. But since pointcut expressions are lengthy, it will be good if instead of repeating we can give a logical name to that pointcut and refer to it by logical name.

So for this we have to first create pointcut config :

package com.xxxx;
//
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class PointcutConfig {

@Pointcut("execution(public * service.*.*(..))") //This is a pointcut expression
public void serviceComponents() {} //This is a name given to the pointcut expression

@Pointcut("execution(* apply*(..))")
public void applyMethods() {}

}



Note that we @Aspect and @Pointcut annotations above.


When we write our own aspect we can simply refer to these method names in pointcut-config now:


import java.util.Date;

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

@Aspect
public class LoggingAspect {

@Before("com.xxxx.PointcutConfig.applyMethods()")
public void log(JoinPoint joinPoint) {
System.out.println("log advice executed for method : "+joinPoint.getSignature().getName());
}

@Before("com.xxxx.PointcutConfig.serviceComponents()")
public void timeLog(JoinPoint joinPoint) {
System.out.println("request for method : "+joinPoint.getSignature().getName()+" occurred at "+new Date());
}
}


In the config file, we have to define both beans:


<aop:aspectj-autoproxy />

<bean id="pointcutConfig" class="ex4.PointcutConfig" />

<bean id="loggingAspect" class="ex4.LoggingAspect" />

<bean class="service.OrderServiceImpl" />

<bean class="service.CustomerServiceImpl" />

Binding parameters to advice

A joinpoint object provides all the details required by the advice to perform any kind of operation.

Suppose we have to validate an order, and so we are writing our own aspect to get argument from pointcut - expression and perform validation. Example:

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

import service.Order;

@Aspect
public class OrderValidator {

@Before("execution(* placeOrder(..)) && args(order)")
public void validateOrder(Order order) {
//some order validation logic here
System.out.println("Just checking it out!");
}
}

In the config file we write:


<aop:aspectj-autoproxy />

<bean class="ex3.OrderValidator" />

<bean class="service.OrderServiceImpl" />


Pointcut expression

The most typical pointcut expressions are used to match a number of methods by their signatures. A common method based pointcut expression is something like

PCD(<method scope> <return type> <fully qualified class name>.*(arguments))


  1. PCD - PCD is pointcut designators. Spring AOP supports following pointcut expression -
    -- execution, with, this,target, args
    --Spring AOP also supports an addition PCD - "bean"
    --Of these, execution is most common
  2. method scope: Advice will be applied to all the methods having this scope. For e.g., public, private, etc. Please note that Spring AOP only supports advising public methods.
  3. return type: Advice will be applied to all the methods having this return type.
  4. fully qualified class name: Advice will be applied to all the methods of this type. If the class and advice are in the same package then package name is not required
  5. arguments: You can also filter the method names based on the types. Two dots(..) means any number and type of parameters.

Also these expressions can be chained to create composite pointcuts : && (and), || (or) , ! (not)


Some examples


the execution of any public method:
execution(public * *(..))

the execution of any method with a name beginning with “set”:
execution(* set*(..))

the execution of any method defined by the MyService interface
execution(* com.xyz.service.MyService.*(..))

the execution of any method defined in the service package:
execution(* com.xyz.service.*.*(..))

the execution of any method defined in the service package or a sub-package:
execution(* com.xyz.service..*.*(..))

any join point (method execution only in Spring AOP) WITHIN the service package:
within(com.xyz.service.*)

any join point (method execution only in Spring AOP) within the service package or a sub-package:
within(com.xyz.service..*)

any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:
this(com.xyz.service.AccountService)

any join point (method execution only in Spring AOP) where the target object implements the AccountService interface:
target(com.xyz.service.AccountService)

any join point (method execution only in Spring AOP) which takes a single parameter, and where the argument passed at runtime is Serializable:
args(java.io.Serializable)

Spring : Advice and its type

Any functionality that exists in an application, but cannot be added in a desirable way is called a cross-cutting concern.

That cross-cutting concern is called aspect-oriented programming (AOP). It deals with the functionality in applications that cannot be efficiently implemented with pure object-oriented techniques.

One of the core features of AOP frameworks is implementing cross-cutting concerns once and reusing them in different places and in different applications. In AOP jargon, the implementation of a cross-cutting concern is called an advice.

AOP frameworks allow you to define which advice is applied to which methods

Spring AOP supports following types of advices
Joinpoint is the point of execution of application, like method.
Spring AOP supports four advice types that each represents a specific scenario for advice implementations:
  • Around advice: Controls the execution of a join point. This type is ideal for advice that needs to control the execution of the method on the target object.
  • Before advice: Is executed before the execution of a join point. This type is ideal for advice that needs to performan action before the execution of the method on the target object.
  • After advice: Is executed after the execution of a join point. This type is ideal for advice that needs to perform an action after the execution of the method on the target object.
  • Throws advice: Is executed after the execution of a join point if an exception is thrown. This type is ideal for advice that needs to performan action when the execution of the method on the target object has thrown an exception.

Using annotation for configuring advices

We again take example of before advice.

Now we add @Aspect at the bean level. But on the method of the Aspect class, we can have annotations depending on what type of method or better advice they are. For before type advice we have @Before annotation.

Creating the aspect class


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

@Aspect
public class LoggingAspect {

//TODO: Try other pointcut expressions also as mentioned in slide no. 203-207
@Before("execution(public * apply*(..))")
public void log(JoinPoint joinPoint) {
System.out.println("common logging code executed for : "+joinPoint);
}
}


Now the bean class is quite cleaner, as we are annotation:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>

<aop:aspectj-autoproxy />

<bean id="customerService" class="service.CustomerServiceImpl" />

<bean id="loggingAspect" class="ex2.LoggingAspect" />

</beans>


Here we are simply logging a simple text before entering the methods. Consider the case when we want to print about arguments.


This is where JoinPoint object comes into picture.


More about JoinPoint Object


Changing the before advice to take care of arguments , etc of the methods.


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

@Aspect
public class LoggingAspect2 {

@Before("execution(public * apply*(..))")
public void log(JoinPoint joinPoint) {
Object proxyObject = joinPoint.getThis();
Object targetBean = joinPoint.getTarget();
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
//some logging code here
}
}



In the above xml file just change the class name of LoggingAspect to LoggingAspect2.


As the names of the method suggest :



  • this : The current executing object that has been intercepted

  • target : The target of the execution (typically our object)

  • args -  method args

  • signature - method signation of the joinpoint

One of the reason why aspectJ was adopted by the spring was because of v.powerful and easy to learn pointcut expression, which define where our aspects will execute.

Spring : Xml style configuration for pointcuts (Before advice)

The Aspect Class:

import org.aspectj.lang.JoinPoint;

//This is an Aspect class
public class LoggingAspect {

//This is an advice.
//Pointcut means where will this advice be applied.
public void log(JoinPoint joinPoint) {
System.out.println("common logging code executed for : "+joinPoint);
}

}

The configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>

<!-- Tells the container we will be using AspectJ.
Also tells the container to use the proxy approach for executing aspects -->
<aop:aspectj-autoproxy />

<bean id="customerService" class="service.CustomerServiceImpl" />

<bean id="loggingAspect" class="com.xxxx.LoggingAspect" />

<!-- Aop config start -->

<aop:config>
<aop:pointcut expression="execution(public * apply*(..))" id="pointcut1" />
<aop:aspect ref="loggingAspect">
<aop:before method="log" pointcut-ref="pointcut1" />
</aop:aspect>
</aop:config>

</beans>


Note that we are using "aop" namespace in the xml to configure it to aspect class.

 


 

AOP : Terminology

Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about program structure. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects enable the modularization of concerns such as transaction management that cut across multiple types and objects.
 

AOP concepts:

• Aspect: a modularization of a concern that cuts across multiple classes. Transaction management is a good example of a crosscutting concern in J2EE applications. In my words: a trigger which can affect the multiple classes a one point….
Aspects are implemented using Spring as Advisors or Interceptors.

• Join point: a point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.

• Advice: action taken by an aspect at a particular join point. Different types of advice include “around,” “before” and “after” advice. (Advice types are discussed below.) In my words : the action to be taken at the point. See here for type of advices.

• Pointcut: Pointcuts are the expression which identify where an advice should apply. Its a predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut expression language by default

• Introduction: declaring additional methods or fields on behalf of a type. Spring AOP allows you to introduce new interfaces (and a corresponding implementation) to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching. (An introduction is known as an inter-type declaration in the AspectJ community.)
• Target object: object being advised by one or more aspects. Also referred to as the advised object. Since Spring AOP is implemented using runtime proxies, this object will always be a proxied object.
• AOP proxy: an object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy will be a JDK dynamic proxy or a CGLIB proxy.