2010-11-29 87 views
2

我正在开发一个方面,它检查我的实体包的setter方法的字符串参数是否为空字符串,并将其替换为null值。但不幸的是我的方面没有行之有效:(我想这是因为我的切入点定义的,但我不知道字符串设置器的Spring AOP切入点定义

我的方面是这样的:。

import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.annotation.Aspect; 

@Aspect 
public class EmptyStringToNullSetter { 
    private static final Logger LOGGER = LoggerFactory 
      .getLogger(EmptyStringToNullSetter.class); 

    public void check(final JoinPoint jp) { 
     LOGGER.debug(jp.getSignature().toLongString()); 
    } 
} 

我的Spring配置看起来像:

<bean id="emptyStringToNullSetter" class="de.foo.util.aop.parameter.EmptyStringToNullSetter" /> 
<aop:config> 
    <aop:pointcut id="entityStringSetter" expression="execution(* de.foo.entity.*.set*(..)) and args(java.lang.String)" /> 
    <aop:aspect id="checkEmptyStringsAspect" ref="emptyStringToNullSetter"> 
     <aop:before method="check" pointcut-ref="entityStringSetter" /> 
    </aop:aspect> 
</aop:config> 

我的测试类的样子:

import de.foo.entity.Period; 

@ContextConfiguration(locations = { "/spring/test-util-context.xml" }) 
public class EmptyStringToNullSetterTest extends 
    AbstractJUnit4SpringContextTests { 
    @Test 
    public void testCheck() { 
     Period period = new Period(); 
     period.setName(""); 
     Assert.assertNull(period.getName()); 
    } 
} 

当我执行我的测试方面不会在关注我的二传手。有谁知道为什么?!

干杯,

凯文

回答

4

由于您使用基于代理的AOP,建议将只适用于春豆与“期”的对象不是一个bean。您需要将“period”作为bean或使用AspectJ的基于AOP的编织。无论哪种情况,您都需要使用周围的建议,而不是之前。

+0

是的,谢谢,你有正确的基于代理的aop,但我认为春天也反射性地做非春豆。无论如何,我会切换到aspectj编织。但为什么我应该使用周围的建议,而不是之前? – eglobetrotter 2010-11-30 08:33:30

+1

建议在建议的连接点之前会添加额外的逻辑,但会继续使用相同的上下文(即建议方法的原始参数)。有了周围的建议,你可以调用proceed()改变的上下文(在你的情况下,null而不是空字符串)。 – ramnivas 2010-12-01 00:09:04

0

这种设计非常棘手,而且基于Spring JDK代理的AOP非常容易出错。

我mentionned这里了这一点:http://doanduyhai.wordpress.com/2011/08/08/spring-aop-advices-on-setters-not-trigged/

基本上,一个方面定义Spring AOP实现在运行时周围原始目标的代理对象包装实现。

在bean的生命周期中,Spring只有在bean完全初始化后才会创建代理,毕竟由setter注入属性。

因此,第一次调用setter时,它不会被建议拦截,因为代理还不存在。

但是,对setter的所有后续调用都将被拦截。

此外,请注意自我调用问题,例如,在另一个目标方法中调用setter()。