MethodBeforeAdvice Example in Spring AOP

Here is an example illustrating before-advice in Spring AOP. The before advice is the advice that is given to a method before it is executed.
In simple words, it is nothing more than code that is executed before the method call.

Theme of the application

The theme of the application is to illustrate the before advice. As this type of advice is executed before the method call, I would like to write code that restricts access to a method if invalid credentials are provided.
In this the method will be taking a User object which contains a username and password properties and printing a hello message followed by his name. Now, the advice code is used to check if username and password equals gowthamgutha. If so, then the target method is called.

Create a project in eclipse

  1. File -> New -> Project -> Java Project
  2. Give the project name spring36 and click Finish 
  3. Now, the project is created.
  4. Under the Project Explorer (in the sidebar) you will see spring36. If you aren't able to see Project Explorer, go to Window menu -> Show view -> Project Explorer.
  5. Right click on the spring36 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 ready

To create a class 

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

Project structure


User.java

 package spring36;

public class User {

private String username;
private String password;

    public User()
    {
      
    }
  
    public User(String username,String password)
    {
        this.username=username;
        this.password=password;
    }

    public void setUsername(String username)
    {
        this.username=username;
    }
  
    public String getUsername()
    {
        return username;
    }
  
    public void setPassword(String password)
    {
        this.password=password;
    }
  
    public String getPassword()
    {
        return password;
    }
  
}

WorkerBean.java - Target class

This is the class that contains the method for which the advice should be given.
package spring36;

public class WorkerBean {

    public void work(User user)
    {
        System.out.println("Hello! "+user.getUsername());
        System.out.println("Our secret code is CODE IN JAVA");
    }
   
}

MethodBeforeAdvice.java - Advice class

This is the class that defines the before advice. The before() method of this class is called before the work() method. Once after the code in this method is executed, automatically the work() method will be executed. Note that this advice is not only for work() method but for all methods that you write in the WorkerBean class.

package spring36;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class AccessRestrictor implements MethodBeforeAdvice{

    @Override
    public void before(Method method, Object[] args, Object returnVal)
            throws Throwable {
       
        // There is only argument for work() and that is User type
        User user=(User)args[0];
       
            if(user==null)
            {
                throw new SecurityException("null user?");
            }
            else if(user.getUsername().equals("gowthamgutha") && user.getPassword().equals("gowthamgutha"))
            {
                System.out.println("Logged in as gowthamgutha\n");
            }
            else
            throw new SecurityException("You are unauthorized to see the secret code");
    }

}

As you can see, each statement, you will automatically understand what's going on in this method.

The method prototype: The method takes three arguments.

Method: This points to the Method to which this advice should be applied to. Using this object, we can call getName(), the types of arguments etc. This is a class in the Java reflection.

Object[] args:  This points to the argument values passed to the method in order. As every class is a sub-class of java.lang.Object, an Object[] is used.

As the work() method takes only a single argument User object, obviously it is the first argument. So args[0] will be a User object.

Object: This is the value returned by the function.

If user is null, then a SecurityException is thrown with the given message. Therefore, the execution is halted.
Else if, the username and password are valid then, the invocation of work() will be done, else a SecurityException with the message Invalid credentials is thrown.

SpringPrg.java - Main class

package spring36;

import org.springframework.aop.framework.ProxyFactory;

public class SpringPrg {

    public static void main(String args[])
    {
        // Create the bean object
        WorkerBean wb=new WorkerBean();
       
        // Create an advice object
        AccessRestrictor restrictor=new AccessRestrictor();
       
        // Create a ProxyFactory object
        ProxyFactory pf=new ProxyFactory();
       
        // Set the target bean object
        pf.setTarget(wb);
       
        // Add the access restrictor advice
        pf.addAdvice(restrictor);
       
        // Get the proxied bean object
        WorkerBean bean=(WorkerBean)pf.getProxy();
       
        // 1. Try giving valid credentials
        bean.work(new User("gowthamgutha","gowthamgutha"));
       
        // 2. Try giving unauthorized user
        // will throw exception
        bean.work(new User("ding","dong"));
       
        // 3. Try passing null
        // will throw exception
        bean.work(null);
    }
   
}

This class will a ProxyFactory object through which we can wrap the advice to a target bean object.
The target bean object is the bean object to whose methods the advice should be applied.
The addAdvice() method adds the specified advice to the target bean. You can add as many as advices as you want and they will be executed in the order they were added.
The getProxy() method returns the bean object to which the advice is applied. Now, when you call the work() method from this object, the before advice is applied to it and if the credentials are ok, then the work() method is called.

Try calling work() method on wb and you will notice the difference between calling them using object returned by getProxy() and calling directly. You will notice that when you call wb.work(), the work method will be executed normally i.e. with no advice being executed before the method is called.

No comments: