Je souhaite surveiller toutes les méthodes publiques de toutes les classes avec une annotation spécifiée (par exemple, @Monitor) (note: l'annotation est au niveau de la classe). Quel pourrait être un point possible pour cela? Remarque: J'utilise le style Spring AOP de @AspectJ.
Réponses
Trop de publicités?Vous devez combiner un type coupe transverse (pointcut) avec une méthode de coupe transverse (pointcut).
Ces pointcuts va faire le travail pour trouver toutes les méthodes publiques à l'intérieur d'une classe marquée avec un @Moniteur annotation:
@Pointcut("within(@org.rejeev.Monitor *)")
public void beanAnnotatedWithMonitor() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Pointcut("publicMethod() && beanAnnotatedWithMonitor()")
public void publicMethodInsideAClassMarkedWithAtMonitor() {}
Les conseils de la dernière coupe transverse (pointcut) qui combine les deux premiers et vous avez terminé!
Si vous êtes intéressé, j'ai écrit une feuille de triche avec @AspectJ style ici avec un correspondant document de l'exemple ici.
À l'aide d'annotations, comme décrit dans la question.
Annotation: @Monitor
Annotation sur la classe, app/PagesController.java
:
package app;
@Controller
@Monitor
public class PagesController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
Annotation sur la méthode, app/PagesController.java
:
package app;
@Controller
public class PagesController {
@Monitor
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
Annotations personnalisées, app/Monitor.java
:
package app;
@Component
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Monitor {
}
Aspect de l'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());
}
}
Activer AspectJ, servlet-context.xml
:
<aop:aspectj-autoproxy />
Inclure AspectJ bibliothèques, pom.xml
:
<artifactId>spring-aop</artifactId>
<artifactId>aspectjrt</artifactId>
<artifactId>aspectjweaver</artifactId>
<artifactId>cglib</artifactId>
Quelque chose comme ca:
@Before("execution(* com.yourpackage..*.*(..))")
public void monitor(JoinPoint jp) {
if (jp.getTarget().getClass().isAnnotationPresent(Monitor.class)) {
// perform the monitoring actions
}
}
Notez que vous ne devez avoir aucun autre conseil sur la même classe avant celle-ci, car les annotations seront perdues après le remplacement du proxy.