views:

676

answers:

3

I'd like to use aspectj to profile a library. My plan was to mark methods that require profiling with an annotation:

@Profiled("logicalUnitOfWork")

And then have an aspect that would fire before and after methods that would use the logicalUnitOfWork to highlight the profiled content.

So, my pointcut to start with looks like this. Note that I don't have the argument for the annotation here; that's one of the things I'm not sure how to do:

pointcut profiled() : execution(@Profiled * *());

before() : profiled () {
    // : the profiled logical name is in this variable:
String logicalEventType;
Profiler.startEvent (logicalEventType);
}

after() returning : profiled() {
    // : the profiled logical name is in this variable:
String logicalEventType;
    Profiler.endEvent (logicalEventType);
}

The methods being profiled would be defined like this:

@Profiled("someAction")
public void doAction (args...) {}

In short, how can I get the value of the @Profiled annotation into the aspect? I don't need to restrict which profiling occurs based on the value, I just need it to be visible to the advice. Also, do I need to have the annotation's retention set to runtime for this to work, or can I have class-level retention instead?

+2  A: 
Bogdan
That certainly helps, although ideally I'd like to have the annotation be retained only in the class file. AspectJ weaving takes place at that point, so I would hope that it could acquire the value.
Chris R
I simplified the original example a bit, but I think you will still have to set the retention to runtime. Class level would suffice if you only wanted to match by annotation, but you also need to access it at runtime to register profiled events.
Bogdan
+1  A: 

I did something similar a while back to annotate fields with "default values". I've tried to adapt it to annotated methods, which shoud work find. You, of course, should add a bit of error checking and null-testing here since I've left that out for brevity's sake.

You can get the value of the annotation using the join point's static part.

private String getOperationName(final JoinPoint joinPoint) {
   MethodSignature methodSig = (MethodSignature) joinPoint
      .getStaticPart()
      .getSignature();
   Method method = methodSig.getMethod();
   Profiled annotation = method.getAnnotation(Profiled.class);
   return annotation.value();
}

To avoid too much reflection, it's probably a good idea to use around advice instead:

around(): profiled() {
   String opName = getOperationName(thisJoinPoint);
   Profiler.startEvent(opName);
   proceed();
   Profiler.endEvent(opName);
}
Steve Reed
A: 

I would strongly advise against using the around advice its overhead is huge in comparison to a tuned before and after.

By the way why implement this when you can use our Probes technology based on an enhanced AspectJ runtime and get costs down to 1 nanosecond for instrumented methods.

http://blog.jinspired.com/?p=655

William Louth