Il y a 15 ans -
Temps de lecture 4 minutes
Activer un aspect par JMX
En mai 2007, Manuel Eveno expliquait comment avec la programmation orientée aspect (AOP) et l’outil Jamon, il est facile de relever des points de mesure dans une application Java / J2EE. Cependant, il existe des situations (exemple : environnement de Production) où l’on aimerait pouvoir activer temporairement ou désactiver complètement ce type d’aspects. Dans cet article, je vais expliquer comment avec l’AOP on peut activer un aspect par JMX.
Voici l’aspect PerfMonitor présenté par Manuel dans son article : le pointcut monitor concerne l’exécution de la méthode methodToMonitor de la classe fr.xebia.appz.ClassToMonitor, quel que soit son nombre de paramètres et sa visibilité. L’advice de prise de mesure est appliqué avant et après le pointcut monitor.
public aspect PerfMonitor { pointcut monitor() : execution(* fr.xebia.appz.ClassToMonitor.methodToMonitor(..)) ; Object around() : monitor() { Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString()); try { return proceed(); } finally { if (monitor != null) monitor.stop(); } } }
Ajouter l’attribut ‘enabled’ à l’aspect
Tout d’abord, il faut ajouter un attribut ‘enabled’ à l’aspect et modifier l’advice pour prendre en compte l’état de l’attribut. Voici le nouveau code de l’aspect PerfMonitor :
public aspect PerfMonitor { private boolean enabled = true; public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } pointcut monitorEnabled() : if(aspectOf().isEnabled()); pointcut monitor() : execution(* fr.xebia.appz.ClassToMonitor.methodToMonitor(..)) ; Object around() : monitor() && monitorEnabled() { Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString()); try { return proceed(); } finally { if (monitor != null) monitor.stop(); } } }
Quelques remarques :
- l’attribut ‘enabled’ est initialisé à la valeur ‘true’ par défaut.
- l’attribut est accessible par les deux méthodes à la manière ‘JavaBean’, isEnabled(), setEnabled()
- un nouveau pointcut monitorEnabled a été défini. Il retourne ‘true’ si l’appel de la méthode de l’aspect isEnabled() retourne ‘true’. L’instruction aspectOf() retourne une référence sur l’aspect, comme le mot-clé this en Java retourne une référence sur l’objet lui-même.
- l’advice a été modifié pour prendre compte le nouveau pointcut. Il sera activé que si les pointcuts monitor et monitorEnabled sont vérifiés.
A partir de là, si la valeur l’attribut ‘enabled’ est égale à false, il n’y aura pas de prise de mesure par l’API Jamon.
Exposition JMX
Avoir un attribut ‘enabled’ est intéressant mais pas suffisant. Il faut pouvoir modifier sa valeur dynamiquement et modifier le comportement au runtime sans nécessiter un redémarrage de la JVM. On pense aussitôt à l’API JMX. Mais comment exposer un aspect par JMX alors qu’à aucun moment on n’est maître de son instanciation ? Un aspect n’est pas une classes sur laquelle on peut appliquer l’operateur new().
Les possibilités offertes par l’AOP à travers l’aspect ‘Management‘ vont nous permettre l’inimaginable !
public aspect Management { public interface ManagedBean { public boolean isEnabled(); public void setEnabled(boolean enabled); } private pointcut managedBeanConstruction(ManagedBean bean) : execution(ManagedBean.new(..)) && this(bean); after(ManagedBean bean) returning: managedBeanConstruction(bean) { ObjectName registered = getMBeanExporter() .registerManagedResource(bean); System.out.println("Bean " + bean + " is exposed with this object name " + registered); } declare parents: PerfMonitor implements ManagedBean; private MBeanExporter getMBeanExporter() { ///Spring Framework Stuff ! } }
L’exposition JMX se fait en 3 temps :
- Le pointcut managedBeanConstruction est vérifié lors de l’exécution de l’instanciation de toute classe implémentant l’interface ManagedBean.
- L’advice suivant est appliqué après le retour du pointcut managedBeanConstruction : il récupère une instance de type org.springframework.jmx.export.MBeanExporter, une classe qui permet d’exposer n’importe quelle classes à l’intérieur d’un MBeanServer, sans qu’il soit nécessaire de définir l’ensemble des informations spécifique à l’API JMX, puis enregistre l’instance de type ManagedBean passé en paramètre comme MBean JMX.
- Le code ‘declare parents: PerfMonitor implements ManagedBean’ indique que maintenant la classe PerfMonitor implémente l’interface ManagedBean. C’est de l’Injection d’interfaces ! L’instruction ‘déclare parent’ permet modifier l’arbre d’héritage d’une classe: dérivation, ajout d’interfaces,… Dans notre cas, le contrat défini par l’interface ManagedBean ajouté à notre Aspect PerfMonitor est déjà rempli par l’aspect lui-même (méthodes isEnabled() et setEnabled()).
Au runtime, dès que le framework AspectJ va procéder à l’instanciation de l’aspect PerfMonitor sous la forme d’une classe Java qui implémente l’interface ManagedBean, l’aspect sera exposé en tant que MBean JMX.
Le screencast suivant détaille les deux aspects (Management et PerfMonitor) et montre sur un exemple très simple le comportement de l’aspect en fonction de la valeur de l’attribut ‘enabled’ modifié par l’outil JConsole
L’ensemble des sources est disponible dans le repository SVN de Xebia France.
Commentaire