Spring is a great Java technology that has become a very popular application framework during the past few years. My intention is not to go through the whole concepts and architectural details of the framework, because that kind of information can be easily looked up starting at
http://www.springframework.org. As the article title indicates, I intend to provide hands-on examples showing the minimal requirements to bundle certain Spring functionalities in your Java applications. So, because I will not go into the “what’s under the hood” approach unless absolutely necessary, most of the examples might require the knowledge of basic Spring concepts. Anyway, the basic idea is that you must RTFM before deciding if Spring is right for your application.
The first example is a short look at a simple method intercepting strategy. You can read all about this and the whole Spring AOP API
here.The source code for this example can be found
here. In the project directory run
ant compile run
to launch the application.
For the beginning let’s consider that we have the service
MyService
that that has a method
doSomething()
performing an operation which takes a long time to execute. Below you can see the (pretty dumb) code of this method.
public class MyService {
public void doSomething() {
for (int i = 1; i < 10000; i++) {
System.out.println("i=" + i);
}
}
}
In order to print out the performance statistics on the method call, we must first implement the interceptor that actually calculates the execution time for this method. To do this we need to implement the
org.aopalliance.intercept.MethodInterceptor
interface shipped with Spring. This is actually a callback providing access to the actual call of the methods of our service. The JavaDoc for this interface is
here.
public class ServiceMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = methodInvocation.proceed();
long duration = System.currentTimeMillis() - startTime;
Method method = methodInvocation.getMethod();
String methodName = method.getDeclaringClass().getName()
+ "." + method.getName();
System.out.println("Method '" + methodName
+ "' took " + duration + " milliseconds to run");
return null;
}
}
Next we need to proxy our service in order to obtain an instance whose methods are being intercepted by our
ServiceMethodInterceptor
. To achieve this, all it takes is a little magic in Spring’s bean configuration file, as you can see below.
<beans>
<bean id="myService" class="com.test.MyService">
</bean>
<bean id="interceptor" class="com.test.ServiceMethodInterceptor">
</bean>
<bean id="interceptedService" class="org.springframework
.aop.framework.ProxyFactoryBean">
<property name="target">
<ref bean="myService"/>
</property>
<property name="interceptorNames">
<list>
<value>interceptor</value>
</list>
</property>
</bean>
</beans>
The key in this XML snippet is Spring’s built-in class
org.springframework.aop.framework.ProxyFactoryBean
which provides the actual proxying of our service. In order to obtain the desired effect we must set the
target
and
interceptorNames
properties for this bean. The
target
property represents the name of the bean that we want to proxy, which in our case is the
myService
bean. The
interceptorNames
property holds a list of bean names that will be used as interceptors for the proxied bean. So, yes, you can define more than one interceptor for your bean.
As everything seems to be packed pretty nice, all we need to do now is to have our service instantiated using Spring and call itâs
doSomething
method.
public class Test {
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("com/test/applicationContext.xml");
MyService myService = (MyService)ctx.getBean("interceptedService");
myService.doSomething();
}
}
So we need to look up the
interceptedService
bean in order to get the proxied service, but if we choose to remove the performance monitor we can simply lookup the initial
myService
bean.
Normally, after the method
doSomething
has run, you should see, as the last output line, something like this:
Method 'com.test.MyService.doSomething' took 281 milliseconds to run
Except from the
MethodInterceptor
Spring also offers other method interception strategies. For example you can choose to handle a method execution right before or immediately after the actual call, or when an exception is thrown during the execution of your method. The reference documentation about these types of interceptors that Spring offers is available
here.
Please note that basic performance monitoring can also be achieved by using Spring’s built-in
PerformanceMonitorInterceptor
. We used this logic just as a sample for method intercepting, but as your intuition might tell you, this is just one of the many things you can do with this feature of Spring. For example, if you need to implement a fine-grained security module, you might choose not to allow the method call to execute if the user does not have rights on the business method. So, basically, you will have to see for yourself how you can use this functionality in your application.
I hope you find this article useful.