如何使用AspectJ修改返回对象的属性?

时间:2012-11-13 22:41:23

标签: aspectj spring-roo pointcut

我有一个类似于下面的类(来自Spring Roo DataOnDemand),它返回一个新的瞬态(非持久化)对象,用于单元测试。这是我们从Spring Roo的ITD进行推入后代码的样子。

public class MyObjectOnDemand {
    public MyObjectOnDemand getNewTransientObject(int index) {
        MyObjectOnDemand obj = new MyObjectOnDemand();
        return obj;
    }
}

我需要做的是对返回的对象引用进行额外调用,以设置Spring Roo自动生成的方法不需要处理的其他字段。因此,如果不修改上述代码(或从Roo的ITD推送它),我想再打一个电话:

obj.setName("test_name_" + index);

为此,我宣布了一个具有正确切入点的新方面,并将建议具体方法。

public aspect MyObjectDataOnDemandAdvise {
    pointcut pointcutGetNewTransientMyObject() : 
        execution(public MyObject MyObjectDataOnDemand.getNewTransientObject(int));

    after() returning(MyObject obj) : 
        pointcutGetNewTransientMyObject() {
         obj.setName("test_name_" + index);
    }
}

现在,根据Eclipse的说法,切入点已正确编写并建议正确的方法。但它似乎没有发生,因为持久化对象的集成测试仍然失败,因为name属性是必需的,但没有设置。根据Manning的AspectJ in Action(第4.3.2节),after建议应该能够修改返回值。但也许我需要做一个around()建议呢?

3 个答案:

答案 0 :(得分:3)

我会在tgharold回复中添加评论,但没有足够的声誉。 (这是我的第一篇文章)

我知道这已经过时了,但我认为这可以帮助那些看到这里的人知道可以使用thisJoinPoint在AspectJ的先前建议或后期建议中获取参数。

例如:

after() : MyPointcut() {
    Object[] args = thisJoinPoint.getArgs();
    ...

更多信息请访问:http://eclipse.org/aspectj/doc/next/progguide/language-thisJoinPoint.html

希望它对某人有用。

答案 1 :(得分:0)

所以,事实证明我在Eclipse中遇到了一个错误,因为它没有正确编织东西。在Spring Roo shell中运行“执行测试”使一切正常,但是作为JUnit测试用例运行包不起作用。

上面的代码使用“返回后”建议。但是你也可以使用“around”建议来实现它,它允许你访问传递给方法的参数。

 MyObject around(MyObjectDataOnDemand dod, int index) :
    pointcutGetNewTransientMyObject() 
    && target(dod) && args(index) {

     // First, we go ahead and call the normal getNewTransient() method
     MyObject obj = proceed(dod, index);

     /*
     * Then we set additional properties which are required, but which
     * Spring Roo's auto-created DataOnDemand method failed to set.
     */
     obj.setName("name_" + index);

     // Lastly, we return the object reference
     return obj;
 }

对于我们的特定情况,“返回后”的建议更简洁,更易读。但是,知道如何使用“around”建议来访问参数也很有用。

答案 2 :(得分:0)

以下是使用的示例:

pointcut methodToMonitor() : execution(@Monitor * *(..));

Object around() : methodToMonitor() {
    Object result=proceed();

    return result;
}