I also don't know how you can bind the complete set of arguments for any/all method signatures. It might be a decent enhancement-request - others on the list may know whether access this has been previously proposed.
For completeness, I believe that the fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=67592 resulted in the array-copy for args, ensuring all advice sees the same args at the join-point (provided of course that a state-changing method is not called on one of the array members). Brett On 15 April 2013 12:42, Jay Roberts <[email protected]> wrote: > Hi Brett, > > Thanks for the links and the response. I had come across that discussion, > but it still didn't meet my needs. > > I understand the logic of getArgs returning the original passed args, those > semantics makes sense. > > But what I can't do is have something like args(..) in the pointcut and bind > to the entire set of arguments. We don't need just one or two of them, we > need all of them brought into scope and bound then so that downstream aspects > may act upon what changes we may make. > > The usage of our aspects are across a wide array of method signatures and we > want to examine all of them via reflection, etc, making decisions about what > to do for each based upon a number of factors. We don't know which of the > params will need modification, replacement in advance, so we would have to > write a whole bunch of point cuts to try to cover this. > > Something that would let us bind to all the arguments as, say, an object array > > @Around("execution( @anno * *(..) && args(..)") > public Object myAdvice(ProceedingJoinPoint jp, Object[] args){ > ……. > } > > Or, and it would be useful, the ability for an aspect to access, at least in > a read only way, the current state of the closure - if it needs to be > modified, jp.proceed(Object[]) already takes care of that. That would > actually allow trailing aspects to understand not just what arguments were > originally passed to the method, but what ones the closure is going to > actually execute on and do this comprehensively for all arguments. It seems > like that is very relevant information for certain aspects, at least in my > limited experience. > > So I appreciate sending on those links, but they really don't help with this > situation. > > I did come up w/a very clunky workaround for our stuff, but I'm thinking that > maybe I'll go back and write an aspect on JoinPointImpl that exposes the > information that we need in our downstream aspects and allows us to have > concise code for upstream aspect. > > Again, thanks for the response, I think AspectJ is terrifically cool, I've > used it on and off over the years, great stuff. > > Best, > > Jay Roberts > > Seems like a natural extension of > On Apr 14, 2013, at 10:00 PM, Brett Randall <[email protected]> wrote: > >> Jay, >> >> This was asked not so long ago on the list - it should be added to a >> FAQ if it is not already there, and perhaps justifies a JavaDoc >> clarficiation. >> >> See also: >> >> http://aspectj.2085585.n4.nabble.com/Modifying-parameters-in-more-than-one-aspect-providing-around-advice-td4650584.html >> http://stackoverflow.com/questions/12843998/modifying-parameters-in-more-than-one-aspect-providing-around-advice >> >> The behaviour you are seeing is expected, but perhaps not obvious. >> They key is that JoinPoint.getArgs() only returns a _copy_ of the >> _original_ method arguments at the join-point. So modifying them in a >> prior aspect and/or reading them in a subsequent aspect will not do >> what you want. >> >> As mentioned by Alexander on the other thread and per his >> code-example, you cannot use getArgs() to do what you want - you need >> to instead bind arguments using args() in your pointcut, and then >> access the arguments via the formal parameter instead of getArgs(), >> e.g. in your FirstAspect: >> >> @Pointcut("execution(@SomeAnnotation * *.foo(..)) && args(myArg)") >> public void anyFoo(Object myArg) {} >> >> @Around("anyFoo(myArg)") >> public Object doAdvice(ProceedingJoinPoint jp, Object myArg) throws >> Throwable{ >> // ... >> if (myArgs instanceof BadArg) { >> System.out.println("replaced BadArg"); >> myArg = new GoodArg(); >> } >> return jp.proceed(new Object[] {myArg}); >> } >> >> .. then in your SecondAspect, bind myArg in the same fashion to read >> the replaced argument. This should make the code work in the way you >> expect. >> >> Brett >> >> >> On 14 April 2013 16:35, Jay Roberts <[email protected]> wrote: >>> Hi, >>> >>> I have a situation where I have several possibly cascading Around advices >>> as simplified below. >>> >>> @Aspect >>> @Precedence(FirstAspect, *) >>> class FirstAspect{ >>> @Around("execution(@SomeAnnotation * *.foo(..))") >>> public Object doAdvice(ProceedingJoinpoint jp) throws Throwable{ >>> Object [] args = jp.getArgs(); >>> for(int i=0;i<args.length : i++){ >>> if(args[i] instanceof BadArg){ >>> args[i] = new GoodArg(); >>> } >>> } >>> jp.proceed(args); >>> } >>> } >>> >>> @Aspect >>> class SecondAspect{ >>> @Around("execution(@SomeAnnotation * *(..))") >>> public Object doAdvice(ProceedingJoinpoint jp) throws Throwable{ >>> Object [] args = jp.getArgs(); >>> // Gets the same args as returned from jp.getArgs() in >>> FirstAspect, >>> // not the modified ones. >>> >>> …. do something but have BadArg instead of GoodArg….. >>> >>> jp.proceed(); >>> } >>> } >>> >>> FirstAspect may or may not appear before SecondAspect, SecondAspect is >>> narrower. I traced through the aspectj source and debugger, and I saw that >>> both FirstAspect and SecondAspect have the same join point, whose args >>> remain the original args passed in the target method call. The args passed >>> in to proceed I see go into state for the AroundClosures and the ones >>> modified in FirstAspect do make it to the target method foo. FirstAspect >>> is correctly executing before SecondAspect. >>> >>> I also see that JoinPoint.getArgs returns a copy of args rather than a >>> reference. And I've read a whole bunch on the web about binding args >>> inside the join point using args. However, this binding requires some >>> name/pattern, and both FirstAspect, SecondAspect match to any method params >>> (..). >>> >>> So how can I modify things such that downstream aspects of FirstAspect will >>> get the modified args passed by FirstAspect to JoinPoint.proceed? Is there >>> a way in the advice matching to bind to args(..) so I can get it as a >>> reference in FirstAspect? Or, can SecondAspect somehow get the >>> AroundClosure state so it can look at those rather than JoinPoint.getArgs()? >>> >>> In the meantime, I've just setup a globally accessible >>> ThreadLocal<Map<JoinPoint, Object[]> variable that aspects (possibly) >>> downstream of FirstAspect can lookup modified args and use those if they >>> exist rather than the JoinPoint.getArgs(). This is pretty clunky >>> workaround for the moment, I feel I am really missing something here. >>> >>> Any help would be appreciated. >>> >>> Thanks1 >>> >>> Jay Roberts >>> _______________________________________________ >>> aspectj-users mailing list >>> [email protected] >>> https://dev.eclipse.org/mailman/listinfo/aspectj-users >> _______________________________________________ >> aspectj-users mailing list >> [email protected] >> https://dev.eclipse.org/mailman/listinfo/aspectj-users > > _______________________________________________ > aspectj-users mailing list > [email protected] > https://dev.eclipse.org/mailman/listinfo/aspectj-users _______________________________________________ aspectj-users mailing list [email protected] https://dev.eclipse.org/mailman/listinfo/aspectj-users
