@AspectJ pointcut for all methods of a class with specific annotation

Solution 1:

You should combine a type pointcut with a method pointcut.

These pointcuts will do the work to find all public methods inside a class marked with an @Monitor annotation:

@Pointcut("within(@org.rejeev.Monitor *)")
public void beanAnnotatedWithMonitor() {}

@Pointcut("execution(public * *(..))")
public void publicMethod() {}

@Pointcut("publicMethod() && beanAnnotatedWithMonitor()")
public void publicMethodInsideAClassMarkedWithAtMonitor() {}

Advice the last pointcut that combines the first two and you're done!

If you're interested, I have written a cheat sheet with @AspectJ style here with a corresponding example document here.

Solution 2:

Using annotations, as described in the question.

Annotation: @Monitor

Annotation on class, app/PagesController.java:

package app;
@Controller
@Monitor
public class PagesController {
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public @ResponseBody String home() {
        return "w00t!";
    }
}

Annotation on method, app/PagesController.java:

package app;
@Controller
public class PagesController {
    @Monitor
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public @ResponseBody String home() {
        return "w00t!";
    }
}

Custom annotation, app/Monitor.java:

package app;
@Component
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Monitor {
}

Aspect for annotation, app/MonitorAspect.java:

package app;
@Component
@Aspect
public class MonitorAspect {
    @Before(value = "@within(app.Monitor) || @annotation(app.Monitor)")
    public void before(JoinPoint joinPoint) throws Throwable {
        LogFactory.getLog(MonitorAspect.class).info("monitor.before, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName());
    }

    @After(value = "@within(app.Monitor) || @annotation(app.Monitor)")
    public void after(JoinPoint joinPoint) throws Throwable {
        LogFactory.getLog(MonitorAspect.class).info("monitor.after, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName());
    }
}

Enable AspectJ, servlet-context.xml:

<aop:aspectj-autoproxy />

Include AspectJ libraries, pom.xml:

<artifactId>spring-aop</artifactId>
<artifactId>aspectjrt</artifactId>
<artifactId>aspectjweaver</artifactId>
<artifactId>cglib</artifactId>

Solution 3:

Something like that:

@Before("execution(* com.yourpackage..*.*(..))")
public void monitor(JoinPoint jp) {
    if (jp.getTarget().getClass().isAnnotationPresent(Monitor.class)) {
       // perform the monitoring actions
    }
}

Note that you must not have any other advice on the same class before this one, because the annotations will be lost after proxying.