Girish
Girish

Reputation: 2011

Aspectj : getting the @Pointcut details in @Aspect

I have an aspect that is called for any of the pointcuts defined, similar to something like this:

@Around("pointcut1(request) || pointcut2(request) || pointcut3(request)")
public ModelAndView myAspect(ProceedingJoinPoint proceedingJp, 
                             HttpServletRequest request)
{
    //do something.
}

So inside this aspect, I need to know that for which pointcut (pointcut1/2/3) this myAspect is called. Is there any why I can get this in aspect?

To add more details .....

Isn't there any parameter that I can get in @Aspect (method). I know I can get JoinPoint , but it doesn't work well for me. Something like this would be very convenient....

@Around("pointcut1(request) || pointcut2(request) || pointcut3(request)")
public ModelAndView myAspect(ProceedingJoinPoint proceedingJp, PointCut pc ,HttpServletRequest request){
if (pc.equals("pointcut1")) {
    //do something.
}
if (pc.equals("pointcut2")) {
    //do something.
}
// ...

}

Please suggest !!

Any more suggestions please !!!

Upvotes: 0

Views: 986

Answers (1)

Andrew Eisenberg
Andrew Eisenberg

Reputation: 28737

The best way to do this is to write advice for each of the component pointcuts and set a flag saying that it has been reached. Due to Aspect precedence (ie- which advice runs before which other advice), you need to ensure that the component advice is lexically above the final around advice. It will look like this:

boolean pointcut1Reached = false;

ModelAndView around(HttpServletRequest request) : pointcut1(request) {
    pointcut1Reached = true;
    try {
         proceed(request);
    } finally {
         pointcut1Reached = false;
    }
}

// ... similar for other pointcuts

@Around("pointcut1(request) || pointcut2(request) || pointcut3(request)")
public ModelAndView myAspect(ProceedingJoinPoint proceedingJp, HttpServletRequest request){
    if (pointcut1Reached) {
        //do something.
    }
    if (pointcut2Reached) {
        //do something.
    }
    // ...
}

Two things to note here:

  1. If your program is multithreaded, then you are going to need to ensure that the instantiation of the aspect is appropriate.
  2. I use code style AspectJ syntax because I have a personal bias against annotation style. :)

To avoid the problems of multithreaded code, you can specify an instantiation model for the aspect.

aspect MyAspect percflowbelow( execution ( * * HttpServletRequest.something(..) ) { ... }

The statement above says that there will be one instance of the aspect instantiated for each cflow below a call to HttpServletRequest.something(). If one of the advice is reached inside the aspect, but it is not in the percflowbelow, then the advice will not be run.

The only trick now is to figure out what kind of pointcut should be placed inside of percflowbelow. Is there some method call way up in the stack that contains all of the pointcuts?

Once you have this figured out, you do not need to worry about multithreading.

Upvotes: 1

Related Questions