Static Pointcuts Example in Spring AOP


The following example illustrates creating a simple static pointcut in Spring AOP. As said in this post, a pointcut is a piece of code that decides for which methods the advice should be applied to.

A static pointcut is a type of point cut which filters methods on the basis of their name, the type of arguments, their class name etc but not by the values of the arguments passed to that method.

Theme of the application

The theme of the application is to illustrate a simple static pointcut. This pointcut defines that the advice should only be applied to a certain method. Here, that method is ding().
The ding() method contains a statement to print is a.
The advice is an around advice i.e. some statements are executed before method invocation and some after method invocation. Now, the statement before calling ding() is Rama and the statement after calling ding() is boy.
Altogether print, Rama is a boy as output. This is a simple program that will better explain a simple static point cut.

Create a project in eclipse

  1. File -> New -> Project -> Java Project
  2. Give the project name spring39 and click Finish 
  3. Now, the project is created.
  4. Under the Project Explorer (in the sidebar) you will see spring39. If you aren't able to see Project Explorer, go to Window menu -> Show view -> Project Explorer.
  5. Right click on the spring39 and click Properties
  6. On the left side, click on Java Build Path.
  7. Select the Libraries tab and then click on Add External Jars
  8. Now, add these jar files starting with: spring-core, aop-alliance, spring-aop, commons-logging
  9. Click on OK and then you are read

To create a class

In the Project Explorer, navigate to spring39 and right click on spring39. Then go to New -> Class and give the name of the class as defined below.

Project structure





SimpleBean.java

This class contains the method ding() for which the advice will be applied. This is the target bean class.
package spring39;

public class SimpleBean {

    public void ding()
    {
        System.out.print("is a");
    }
   
    public void dong()
    {
        System.out.println("is not");
    }
   
}

SimpleAdvice.java - Around advice

This is the class that contains the advice code that will be applied.
package spring39;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

// A sample around advice
public class SimpleAdvice implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
       
        // Statement before method exeuction
        System.out.print("Rama ");
       
        // This method is used to proceed to next before/around advice (if any)
        // otherwise, method is called simply
        Object val=mi.proceed();
       
        // Statement after method execution
        System.out.print(" boy");
       
        // Return the val, that indidates
        // that the method is invoked successfully
        // Next intercept will be proceeded if the val is returned
        return val;
    }

}

SimpleAdvice is the only advice defined in this example, so mi.proceed() invokes the method. Note that the invoke() method is called only for those methods that satisfy the pointcut below.

SimpleStaticPointcut.java

package spring39;

import java.lang.reflect.Method;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.StaticMethodMatcherPointcut;

// A point cut defines methods for which the advice should be applied to
public class SimpleStaticPointcut extends StaticMethodMatcherPointcut {

    // Filters classes, this is executed first
    @Override
    public ClassFilter getClassFilter() {
        return new ClassFilter(){
           
            @Override
            public boolean matches(Class<?> cls) {
                // Only if the name of the class ends with SimpleBean
                return cls.getName().endsWith("SimpleBean");
            }
           
        };
    }

    // After matching the class, now lets go to the
    // methods in that class
    @Override
    public boolean matches(Method method, Class<?> cls) {
       
        // Only if the method name equals ding
        return (method.getName().equals("ding"));
    }

}

Here, first the class on whose object the method is called, is filtered. So getClassFilter() is first called. If the ClassFilter code decides to execute the method on that class. Then the matches() method is executed.

The matches() method is executed once for every method no matter how many times it is called. When the matches() is executed for a method, its value is cached i.e. whether that method is as specified in the matches().

Here, the code returns that only method with name ding() is allowed. Therefore, the invoke() method in the advice class is called only when ding() is called. So the advice is applied only for ding() but not for dong().

Now, ding() matches the pointcut, so its value is true. Next, dong() doesn't match the pointcut, so matches() will return false for dong(). Both these values are cached.

 First, matches() method is called on all the methods when you call getProxy() method. Next, again it is called when you call those methods the first time only. After, that no matter how many times you call those methods, matches() will not be called.

SpringPrg.java - Main class

package spring39;

import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class SpringPrg {

    public static void main(String args[])
    {
        // Create target bean object
        SimpleBean sb=new SimpleBean();
       
        // Create a point cut that is static
        // a point cut defines which method(s) on
        // the target object should the advice be
        // applied to
        Pointcut p=new SimpleStaticPointcut();
       
        // An advice is the code that is a cross-cutting
        // concern
        Advice advice=new SimpleAdvice();
       
        // An advisor is a combination of advice and point cut
        // i.e. it defines to whom the advice should be given
        // and also the advice to be given
        Advisor advisor=new DefaultPointcutAdvisor(p,advice);
       
        // Create a ProxyFactory object
        ProxyFactory pf=new ProxyFactory();
       
        // Add the advisor
        // With this you are adding both the advice
        // and to which methods that should be applied
        pf.addAdvisor(advisor);
               
        // Set the target object
        pf.setTarget(sb);

        // Get the bean that is wrapped with advice
        SimpleBean bean=(SimpleBean)pf.getProxy();

        // call the proxied methods
        bean.ding();
       
        // a new line to separate both lines
        System.out.println();
       
        // call dong (advice will not be applied
        // to this method) as defined in the point cut
        bean.dong();
    }
   
}

Output


Rama is a boy
is not

No comments: