Spring AOP advices on setters not trigged

A few days ago I had to enhance some text value injected into one of my bean


<bean id="myBean">
<property name="featureName" value="${global.properties.feature.name}" />
</bean>

The idea was to modify the injected “feature” value with an @Around AOP poincut:


@Around("execution(* com.test.MyBean.setFeature(..))")
public Object enhanceFeatureName(ProceedingJoinPoint jp) throws Throwable
{
	Object[] args = jp.getArgs();
	args[0] = ...// new value of feature name here
	return jp.proceed(args);
}

To my great despair, this wasn’t working at all. In debug mode, the enhanceFeatureName() method was never called. I’ve tried everything, changing the poincut expression, turning the @Around advice into a @Before advice, using XML declarative AOP  instead of annotation, nothing seemed to work.

With a @Before advice, you can read the value of all input arguments but you cannot change them. The returned Object[] args array is a COPY of the original arguments array. The only way to modify input parameters is using @Around advice and calling proceedingJointPoint.proceed(modifiedArgs).

Indeed, there is a big flaw in this design. Basically, an AOP proxy is created for the bean only AFTER the bean complete initialization, e.g. after all properties are injected by setter. So when the setFeature() is called for the first time, the AOP proxy did not exist yet. No wonder the enhanceFeatureName() method was never called.

However all subsequent calles to the setter, after the proxy has been set-up, will be intercepted properly.

The only solution for this problem is to rely on AspectJ with compile-time weaving, bypassing the Spring initialization process.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.