The following example illustrates using a dynamic pointcut. The difference between a static pointcut is that, in dynamic pointcut you can filter the method call instead of just the method. For example, you can apply the advice to
To achieve this, the dynamic pointcut is called every time the method is invoked because every time it is invoked, the argument value might change.
This method takes an int parameter and prints the value. Now, an around advice is applied to it.
This advice contains the code that logs two messages. One message is printed before the method is invoked and the other after the method is invoked.
Now, we will be writing a pointcut to let the advice apply to only when the value passed to ding() is other than 100.
ding(10);
but not ding(20);
In simple words, here you will get access to the argument values.To achieve this, the dynamic pointcut is called every time the method is invoked because every time it is invoked, the argument value might change.
Theme of the application
The theme of the application is to illustrate a simple dynamic pointcut. Here, the method for which the advice will be applied isding()
. The prototype of this method is as follow public void ding(int x);
This method takes an int parameter and prints the value. Now, an around advice is applied to it.
This advice contains the code that logs two messages. One message is printed before the method is invoked and the other after the method is invoked.
Now, we will be writing a pointcut to let the advice apply to only when the value passed to ding() is other than 100.
Create a project in eclipse
- File -> New -> Project -> Java Project
- Give the project name spring41 and click Finish
- Now, the project is created.
- Under the Project Explorer (in the sidebar) you will see spring41. If you aren't able to see Project Explorer, go to Window sajian -> Show view -> Project Explorer.
- Right click on the spring41 and click Properties
- On the left side, click on Java Build Path.
- Select the Libraries tab and then click on Add External Jars
- Now, add these jar files starting with: spring-core, aop-alliance, spring-aop, commons-logging
- Click on OK and then you are read
To create a class
In the Project Explorer, navigate to spring41 and right click on spring41. Then go to New -> Class and give the name of the class as defined below.
Project structure
SimpleBean.java
This is the sasaran bean class that contains the method ding() for which the advice is wrapped.
package spring41;
public class SimpleBean {
public void ding(int x)
{
System.out.println("The value is "+x);
}
}
MySimpleAdvice.java - Around advice
package spring41;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MySimpleAdvice implements MethodInterceptor {
// Create a log object
private static Log log;
static
{
// Create the log object
log=LogFactory.getLog(MySimpleAdvice.class);
}
public Object invoke(MethodInvocation mi) throws Throwable
{
// Print the method call
String name=mi.getMethod().getName()+"("+mi.getArguments()[0]+")";
Object val=null;
if(log.isInfoEnabled())
{
// log the detail
log.info("Invoking method "+name);
// call the method
val=mi.proceed();
// print method is invoked
log.info("Method is invoked.");
}
// return val
return val;
}
}
SimpleDynamicPointcut.java
This class defines to which the advice should be applied.
package spring41;
import java.lang.reflect.Method;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.DynamicMethodMatcherPointcut;
public class SimpleDynamicPointcut extends DynamicMethodMatcherPointcut {
// Filter the sasaran class first
@Override
public ClassFilter getClassFilter() {
return new ClassFilter(){
@Override
public boolean matches(Class<?> cls)
{
// Only SimpleBean class, not other classes
return cls.getName().endsWith("SimpleBean");
}
};
}
@Override
public boolean matches(Method method, Class<?> cls, Object[] args) {
// Filter the method name, only for ding()
// advice should be applied
if(!method.getName().equals("ding")) return false;
// Get the first argument
int x=(Integer)args[0];
// If x!=100 then it matches, else doesn't
return x!=100;
}
}
First, the
getClassFilter()
method is executed first and next matches()
is executed. Here as you can see, the last argument is args which is of type Object[]
. These are argument values passed to the method in order. SpringPrg.java - Main class
package spring41;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class SpringPrg {
public static void main(String args[])
{
// Create sasaran bean object
SimpleBean sb=new SimpleBean();
// Create the pointcut object
SimpleDynamicPointcut pointcut=new SimpleDynamicPointcut();
// Create advice object
MySimpleAdvice advice=new MySimpleAdvice();
Advisor advisor=new DefaultPointcutAdvisor(pointcut,advice);
// Create ProxyFactory
ProxyFactory pf=new ProxyFactory();
// Set the sasaran object
// Only methods in this object will be filtered
pf.setTarget(sb);
// Add the advisor
pf.addAdvisor(advisor);
// Get the proxied object
SimpleBean bean=(SimpleBean)pf.getProxy();
// Logging will be displayed
// since x!=100
bean.ding(10);
bean.ding(101);
// logging will not be displayed
bean.ding(100);
}
}
When you call ding(10) and ding(101) the advice will be applied, but not for ding(100).
Output
Apr 13, 2014 1:25:28 PM spring41.MySimpleAdvice invoke
INFO: Invoking method ding(10)
The value is 10
Apr 13, 2014 1:25:28 PM spring41.MySimpleAdvice invoke
INFO: Method is invoked.
Apr 13, 2014 1:25:28 PM spring41.MySimpleAdvice invoke
INFO: Invoking method ding(101)
The value is 101
Apr 13, 2014 1:25:28 PM spring41.MySimpleAdvice invoke
INFO: Method is invoked.
The value is 100
Also see method static pointcut example