@AspectJ pointcut for all methods of a class with specific annotation
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.
Using annotations, as described in the question.
Annotation: @Monitor
Annotation on class, app/PagesController.java
:
package app;@Controller@Monitorpublic class PagesController { @RequestMapping(value = "/", method = RequestMethod.GET) public @ResponseBody String home() { return "w00t!"; }}
Annotation on method, app/PagesController.java
:
package app;@Controllerpublic 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@Aspectpublic 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>
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.