I have a class that looks like follows (from Spring Roo DataOnDemand) which returns a new transient (not persisted) object for use in unit testing. This is what the code looks like after we do a push-in from Spring Roo's ITD.
public class MyObjectOnDemand {
public MyObjectOnDemand getNewTransientObject(int index) {
MyObjectOnDemand obj = new MyObjectOnDemand();
return obj;
}
}
What I need to do is make additional calls on the returned object reference to set additional fields that Spring Roo's auto-generated method is not taking care of. So without modifying the above code (or pushing it in from Roo's ITD), I want to make one additional call:
obj.setName("test_name_" + index);
To do this, I have declared a new aspect which has the proper pointcut and which is going to advise the specific method.
public aspect MyObjectDataOnDemandAdvise {
pointcut pointcutGetNewTransientMyObject() :
execution(public MyObject MyObjectDataOnDemand.getNewTransientObject(int));
after() returning(MyObject obj) :
pointcutGetNewTransientMyObject() {
obj.setName("test_name_" + index);
}
}
Now, according to Eclipse, the pointcut is written properly and is advising the proper method. But it doesn't seem to be happening because the integration tests which persist out the object are still failing because the name attribute is required, but is not being set. And according to Manning's AspectJ in Action (section 4.3.2) the after advice is supposed to be able to modify return values. But maybe I need to do an around() advice instead?
I would have added a comment to tgharold response, but don't have enough reputation. (This is my first post)
I know this is old, but I think it could help others who are looking here to know that it's possible to obtain the arguments in a before advice or an after advice in AspectJ using thisJoinPoint
.
For example:
after() : MyPointcut() {
Object[] args = thisJoinPoint.getArgs();
...
More information at: http://eclipse.org/aspectj/doc/next/progguide/language-thisJoinPoint.html.
Hope it's usefull for somebody.
So, it turns out that I got bit by a bug in Eclipse because it wasn't weaving things properly. Running "perform tests" in the Spring Roo shell made everything work, but running the package as a JUnit test case wasn't working.
The above code does work using "after returning" advise. But you can also implement it using "around" advice, which lets you access the arguments that were passed to the method.
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;
}
For our particular case, the "after returning" advice was more concise and readable. But it's useful to also know how to use the "around" advice to get access to the arguments.
Here's example of using around:
pointcut methodToMonitor() : execution(@Monitor * *(..));
Object around() : methodToMonitor() {
Object result=proceed();
return result;
}
来源:https://stackoverflow.com/questions/13370167/how-to-modify-the-attributes-of-a-returned-object-using-aspectj