J'ai avancé jusqu'à un point où je me trouve bloqué, sans savoir si je peux ou non passer l'obstacle.
J'ai écrit cet aspect, qui se fonde sur les interfaces Localisable dont j'ai parlé :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| /**
* Aspect provoquant la circulation de locales entre objets lors de leur création.
*/
@Aspect public class CirculationDeLocales
{
/**
* Déclaration du pointcut de circulation de locales d'un objet à un autre, pour alimenter un objet créé avec les locales de celui qui l'a créé.
* @param cible Objet localisable à créer.
* @param appelant Objet localisable créateur de l'objet.
*/
@Pointcut("target(cible) && this(appelant) && (execution((LocalisableIF+).new(..)))")
public void declarationCirculation(@SuppressWarnings("unused") LocalisableIF appelant, @SuppressWarnings("unused") LocalisableIF cible)
{
}
/**
* Provoquer la circulation de locales d'un objet à un autre, pour alimenter un objet créé avec les locales de celui qui l'a créé.
* @param cible Objet localisable à créer.
* @param appelant Objet localisable créateur de l'objet.
*/
@After("declarationCirculation(appelant, cible)")
public void circulation(LocalisableIF appelant, LocalisableIF cible)
{
Validate.notNull(cible, "La cible du passage de locales ne peut pas valoir null."); //$NON-NLS-1$
Validate.notNull(appelant, "La source du passage de locales ne peut pas valoir null."); //$NON-NLS-1$
Ressources rsc = new Ressources(CirculationDeLocales.class);
if (rsc.isDebugEnabled())
rsc.debug("log.circulation_locale", cible.getClass().getName(), appelant.getClass().getName()); //$NON-NLS-1$
cible.setLocales(appelant.getLocales());
}
} |
Mais le test que j'ai prévu pour valider mon aspect et qui utilise un objet ObjetNonMetierLocalisable implements LocalisableIF – un objet qui s'initialise par défaut avec la Locale par défaut du système (fr_FR, pour moi) – n'a pas fonctionné comme souhaité.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| /**
* Test de l'aspect "Circulation des locales".
*/
public class TestAspectCirculationLocales
{
@SuppressWarnings("javadoc")
public class A extends ObjetNonMetierLocalise
{
public B creerB()
{
B b = new B();
return(b);
}
}
@SuppressWarnings("javadoc")
public class B extends ObjetNonMetierLocalise
{
}
/**
* Une circulation de locales d'un objet A à un objet B.
*/
@Test public void circulationSimple()
{
// Nous attribuons à un objet A des locales.
Locales localesAppelant = new Locales(Locale.FRENCH, Locale.ITALY);
A a = new A();
a.setLocales(localesAppelant);
assertEquals("A n'a pas convenablement fixé ses locales de départ.", localesAppelant, a.getLocales()); //$NON-NLS-1$
// Et nous créons un objet B par le biais de A. L'aspect est supposé se déclencher après le new.
B b = a.creerB();
// Dans les locales de l'objet créé, nous devons retrouver celles de l'appelant.
Locales localesCible = b.getLocales();
assertNotNull("L'objet créé n''a reçu aucune locale de l'appelant.", localesCible); //$NON-NLS-1$
assertEquals("Les locales de l'objet créé ne sont pas celles de l'appelant.", localesAppelant, localesCible); //$NON-NLS-1$
}
} |
Il échoue sur la dernière assertion, par un message :
"Failed tests: circulationSimple(test.utils.localisation.TestAspectCirculationLocales): Les locales de l'objet créé ne sont pas celles de l'appelant. expected:<[fr, it_IT]> but was:<[fr_FR]>".
Si je le passe en debug, j'arrive bien dans l'aspect qui s'exécute normalement. À ceci près que les paramètres appelant et cible désignent les mêmes pointeurs. De sorte que quand je fais le :
cible.setLocales(appelant.getLocales());
je donne un coup d'épée dans l'eau : je me réaffecte à moi-même ce que j'ai déjà.
D'après ce que j'ai lu d'AspectJ,
il est normal pour un pointcut en initialize de renvoyer pour valeurs de target et this le même pointeur parce que AspectJ se considère à l'intérieur du constructeur sans rien savoir d'autour.
Mais, en revanche, avec un pointcut en execution, j'espérais qu'il me mettrait pour :
- this(appelant) : l'objet qui a entrepris d'en créer un autre, c'est à dire : A a;
- target(cible) : l'objet qui vient d'être créé, B b;
Or donc, mes paramètres appelant et cible désignent tous deux B b.
J'ai essayé de replacer l'execution par un call,
@Pointcut("target(cible) && this(appelant) && (call((LocalisableIF+).new(..)))")
mais mon aspect n'a même pas été tissé, sans que je comprenne bien pourquoi (je suis très jeune sur les aspects).
Il y a t-il une solution pour obtenir le résultat que je désire, ou bien suis-je devant une impossibilité d'AspectJ ?
Merci !
Grunt.
Partager